今天我想知道c ++析构函数,所以我写了一个小测试程序.这回答了我原来的问题,但提出了一个新问题:
以下程序:
#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;
class test
{
public:
int id;
vector<test> collection;
test(){}
test(int id_in){id = id_in;}
~test(){cout << "dying: " << id << "\n";}
};
int _tmain(int argc, _TCHAR* argv[])
{
{
test obj(1);
obj.collection.push_back(test(2));
obj.collection.push_back(test(3));
cout << "before overwrite\n";
obj = test(4);
cout << "before scope exit\n";
}
int x;
cin >> x;
}
Run Code Online (Sandbox Code Playgroud)
产生以下输出:
dying: 2
dying: 2
dying: 3
before overwrite
dying: 2
dying: 3
dying: 4
before scope exit
dying: 4
Run Code Online (Sandbox Code Playgroud)
为什么我没有看到id为1的测试对象的析构函数?如果它被覆盖时没有调用析构函数,那么调用其向量中实例的析构函数是什么?
那是因为你没有实现赋值运算符,所以代之以完成了成员赋值.所以这一行:
obj = test(4);
Run Code Online (Sandbox Code Playgroud)
导致id第一个object(test obj(1))被覆盖4.最后一行dying: 4是破坏那个对象.
您通过创建析构函数违反了规则三,但没有赋值运算符.
通过阅读,您可以按如下方式解释您的代码:
当行
obj = test(4);
Run Code Online (Sandbox Code Playgroud)
编译时,test使用id 4创建临时实例.
然后,调用赋值运算符.由于您没有提供一个,编译器为您生成了一个如下所示:
test& operator=(const test& other)
{
id = other.id;
collection = other.collection;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
id 1只是用临时的4覆盖,对于集合赋值,std::vector调用赋值运算符.
std::vector的赋值运算符删除所有以前包含的元素,这就是你看到的原因
dying: 2
dying: 3
Run Code Online (Sandbox Code Playgroud)
在你的输出中.最后,删除临时创建的id为4的obj实例,导致
dying: 4
Run Code Online (Sandbox Code Playgroud)
第一次出现.如果obj超出范围,你看
dying: 4
Run Code Online (Sandbox Code Playgroud)
输出一次.