当覆盖堆栈上的对象时,不会调用析构函数

时间:2012-08-17 10:41:36

标签: c++ destructor

今天我想知道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;
}

产生以下输出:

dying: 2
dying: 2
dying: 3
before overwrite
dying: 2
dying: 3
dying: 4
before scope exit
dying: 4

为什么我没有看到id为1的测试对象的析构函数?如果它被覆盖时没有调用它的析构函数,那么调用其向量中实例的析构函数会被调用吗?

4 个答案:

答案 0 :(得分:6)

那是因为你没有实现赋值运算符,所以代之以完成了成员赋值。所以这一行:

obj = test(4);

导致第一个对象(id)中的test obj(1)被覆盖为4。最后一行dying: 4来自于破坏那个对象。

答案 1 :(得分:6)

您通过创建析构函数违反Rule of Three,但没有赋值运算符。

通过阅读,您可以按如下方式解释您的代码:

当行

obj = test(4);
编译

,使用id 4创建test的临时实例。

然后,调用赋值运算符。由于您没有提供一个,编译器为您生成了一个如下所示:

test& operator=(const test& other)
{
    id = other.id;
    collection = other.collection;
    return *this;
}

id 1只是用临时的4覆盖,对于集合赋值,调用std::vector的赋值运算符。

std::vector的赋值运算符会删除所有以前包含的元素,这就是您看到

的原因
dying: 2
dying: 3
输出中的

。最后,删除临时创建的id为4的obj实例,导致

dying: 4

第一次出现。当obj超出范围时,您会看到

dying: 4

再次输出。

答案 2 :(得分:3)

执行此操作时,

obj不会被破坏:

obj = test(4);

所有发生的事情是创建一个test(4)并将其分配到现有对象上,因此{1}的1将被4覆盖,这就是为什么你看到最后一个为:

id

答案 3 :(得分:0)

你没有看到1,因为你在最后破坏了obj。在你通过test(4)重写它之前。因此1由4重写。