奇怪的物体破坏
Strange Destruction of objects
我不明白为什么析构函数被调用了这么多次。
#include <iostream>
#include <vector>
class Box
{
public:
int x;
Box(int x);
~Box();
};
Box::~Box()
{
std::cout << x << " Destroyedn";
}
Box::Box(int x)
{
this->x = x;
std::cout << x << " Createdn";
}
int main()
{
std::vector<Box> boxList;
for (int i = 0; i < 3; i++)
{
Box b(i);
boxList.push_back(b);
}
return 0;
}
输出:0 Created
0 Destroyed
1 Created
0 Destroyed
1 Destroyed
2 Created
0 Destroyed
1 Destroyed
2 Destroyed
main退出后,将打印此内容。我在析构函数中保留了一个getchar()来停止程序的执行。否则我们将看不到这些行被打印。
0 Destroyed
1 Destroyed
2 Destroyed
谁能解释一下。
其他答案正确地提到了隐式复制构造函数的调用。要查看这些调用,只需将隐式复制构造函数替换为显式复制构造函数:
#include <iostream>
#include <vector>
class Box
{
public:
int x;
int copy_nr;
Box(int x);
Box(const Box& other); //copy constructor
~Box();
};
Box::~Box()
{
std::cout << x << " (copy " << copy_nr << ") Destroyed" << std::endl;
}
Box::Box(int x) : x(x), copy_nr(0)
{
std::cout << x << " (copy " << copy_nr << ") Created" << std::endl;
}
Box::Box(const Box& other) : x( other.x ), copy_nr( other.copy_nr + 1 )
{
std::cout << x << " (copy " << other.copy_nr <<") Copied"
" (creating copy " << copy_nr << ")" << std::endl;
}
int main()
{
std::vector<Box> boxList;
for (int i = 0; i < 3; i++)
{
Box b(i);
boxList.push_back(b);
}
return 0;
}
在我的机器上,这会产生:
0 (copy 0) Created
0 (copy 0) Copied (creating copy 1)
0 (copy 0) Destroyed
1 (copy 0) Created
1 (copy 0) Copied (creating copy 1)
0 (copy 1) Copied (creating copy 2)
0 (copy 1) Destroyed
1 (copy 0) Destroyed
2 (copy 0) Created
2 (copy 0) Copied (creating copy 1)
0 (copy 2) Copied (creating copy 3)
1 (copy 1) Copied (creating copy 2)
0 (copy 2) Destroyed
1 (copy 1) Destroyed
2 (copy 0) Destroyed
0 (copy 3) Destroyed
1 (copy 2) Destroyed
2 (copy 1) Destroyed
结果可能在其他机器上有所不同,因为std::vector
的实现可以决定何时重新分配其内部数组。
有两个原因。
首先,push_back
有时扩展向量的大小,重新分配空间,复制那里的所有对象,并销毁旧对象。为了摆脱这种重新分配的工件,您可以在循环之前添加boxList.reserve(3)
,并获得更易于理解的输出:
0 Created
0 Destroyed
1 Created
1 Destroyed
2 Created
2 Destroyed
0 Destroyed
1 Destroyed
2 Destroyed
其次,push_back
复制本地b
对象,然后销毁b
。这解释了为什么上面输出的每个对象在创建后很快就被销毁。
最后三个调用当然是在程序出口。
创建0
创建本地Box b(0),复制到vector
0摧毁
,摧毁了
1创建
现在创建了本地Box b(1)
0摧毁
我认为此时你的向量被重新分配,需要将对象复制到新的存储空间。在原始向量中索引为0的对象在
过程中被销毁1了
本地Box被销毁
2创建
现在是索引为2的本地Box的时间了
0摧毁1摧毁了
vector再次被重新分配需要销毁原位置的对象
2了
局部变量被销毁
发生这种情况是因为vector
使用Box
的默认复制操作符来创建对象的第二个实例,绕过了您定义的构造函数。实际上,您确实有两个Box
实例:b
和boxList[i]
。
请注意,如果显式地将赋值操作符定义为private,会对编译器产生什么影响:
class Box
{
public:
int x;
Box(int x);
~Box();
private:
Box& operator=( const Box& second ) {};
};
std中的大量编译错误是由于它在内部使用operator=来创建b
对象的精确副本。
您将得到一个自动生成的复制构造函数。如果你替换
Box b(i);
boxList.push_back(b);
boxList.emplace_back(i);
你得到了现场施工。如果您还使用reserve(3)
(在添加项之前),向量不必移动东西(调用析构函数的另一个可能原因),那么析构函数应该被调用3次
- 没有找到相关文章