堆栈上的对象被覆盖时未调用析构函数

Destructor not called when object on stack is overwritten

本文关键字:调用 析构函数 覆盖 对象 堆栈      更新时间:2023-10-16

今天我想知道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 overwriten";
        obj = test(4);
        cout << "before scope exitn";
    }
    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的测试对象的析构函数?如果它的析构函数在被覆盖时没有被调用,那么什么会调用它向量中实例的析构因子呢?

您创建了一个析构函数,但没有赋值运算符,这违反了三规则。

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

当线路

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

再次输出。

这是因为您没有实现赋值运算符,所以改为执行成员赋值。所以这行:

obj = test(4);

使得第一个对象(test obj(1))中的CCD_ 5被重写为CCD_。最后一行dying: 4来自于摧毁那个物体。

执行以下操作时,obj不会被破坏:
obj = test(4);

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

dying: 4

您看不到1,因为您在最后销毁了obj。在你通过测试(4)重写它之前。因此,1被4重写。

关于实践中的行为,语句

    obj = test(4);

将CCD_ 12成员的值改变为CCD_。因此,当该对象被销毁时,它报告id为4的对象被销毁。分配执行成员分配,因为您尚未定义复制分配运算符。

关于形式上保证的行为,只有当代码中的非标准"stdafx.h"标头定义了宏_tmain_TCHAR,使得预处理产生标准所需的标准main函数时,才有这种能力(对于托管实现):

C++11§3.6.1/1
“程序应包含一个名为main的全局函数,该函数是程序的指定起点。它实现定义了是否需要独立环境中的程序来定义主函数”

虽然不太可能,但这意味着,如果标头没有适当地定义这些宏,那么原则上,无论代码的其余部分是什么,都可以获得您看到的输出。

确保未定义行为不会发生的一种方法是简单地使用标准main

毕竟,截至2012年,使用那些旨在支持Windows 9x的Microsoft宏绝对没有优势,尤其是考虑到微软在2001年就已经使用了Unicode层,使这些宏过时

也就是说,在10年后继续使用它们,只是毫无意义的混淆和增加工作,包括你不能正式说你的程序必须产生任何特定的结果。