何时从列表中弹出对象?

us2*_*012 3 c++ stl

这可能是一个非常愚蠢/基本的问题,但我无法弄明白.我会告诉你我的想法 - 如果我错了,请纠正我.

当我们使用STL容器存储原始指针时,我们必须在它们之后进行清理:

std::list<animal*> alist;
animal *a = new animal();
alist.push_back(a);
...
animal *b = alist.front();
alist.pop_front();
//do stuff with b
delete b;
Run Code Online (Sandbox Code Playgroud)

如果我们存储对象会发生什么?我的理解是,如果一个装满了对象的容器超出范围,它内部的所有对象都将被销毁.正确?

但是,如果我们使用std::list<T>.pop_front()例如从容器中删除对象怎么办?

std::list<animal> alist;
{
  animal ani();
  //ani is inserted at the end of the list (it IS ani rather than a copy 
  //since push_back accepts const T&)
  alist.push_back(ani);
} //nothing is deallocated/destroyed here
...
{
  animal b = alist.front(); //b is now a copy(?!) of the front element
                            //created via copy constructor
  alist.pop_front(); //the front element of the list is 
                     //destroyed/destructor is called 
  //do stuff with b
} //b goes out of scope
Run Code Online (Sandbox Code Playgroud)

Jer*_*fin 6

当您将某些东西存储在容器中时,您传递的任何内容都会被复制到容器1中.你仍然拥有原始对象2 ; 容器拥有其对象的副本.确实push_back(例如)通过引用获取其参数.这意味着当您将对象传递到容器中时,不需要复制用作参数本身,但放入容器的内容仍然是您告诉它推送的内容的副本.通过引用传递意味着只有一个需要副本; 如果它是通过值传递的(至少在C++ 98/03中)会产生两个副本:从对象到函数参数的一个副本,然后从函数参数到容器的另一个副本.通过引用传递允许直接从原始对象的单个副本直接进入容器.

同样,当您从容器中获取对象时,您将获得容器中的对象的副本.容器仍然有它的对象,你有你的对象.每个都有自己的生命.

当您从容器中擦除或弹出一个对象时,该对象将从容器中删除并销毁 - 如果它是具有析构函数的东西,则将调用析构函数来销毁它.

当容器本身被销毁时,容器中的对象将被销毁.无论何时碰巧,你的对象都会被销毁 - 它来自容器的事实对它没有任何影响.如果它是一个局部变量,它将在超出范围时被销毁.如果它是全局的,它将持续到结束时间(对于程序).如果从函数返回它并且用于初始化引用,则会观察到延长其生命周期的常规规则.底线:在那一点上,它只是另一个对象,它将具有与以同样方式定义的任何其他对象一样的生命周期.

当/如果你将指针(原始或智能)存储在容器中时,这可能会有点...模糊.以上所有内容实际上都是正确的,被复制/存储的对象是指针.除非你使用一些"知道"你正在存储指针的容器(例如,Boost ptr_vector),它只是处理一个指针,并"忽略"某个地方有一个指针指向的对象.


  1. 例如,在C++ 11中,您可以使用emplace_back在容器中构建对象,但同样的基本思想适用 - 容器具有它拥有的对象,并且您永远不会直接触摸.
  2. 在这里,我使用的"对象"更像是非程序员 - 只是表示"某些东西",不一定是类的实例.在C使用单词的意义上它甚至可能不是"对象" - 它可能是纯粹的右值(例如push_back(10)).