【问题标题】:c++ - wrong destructor gets calledc++ - 错误的析构函数被调用
【发布时间】:2013-07-10 20:16:58
【问题描述】:

我对析构函数有一个理解问题。

在以下示例中:

#include <iostream>

using namespace std;

class X{
public:
    int id;
    X(int id){
        this->id = id;
    }
    ~X(){
        cout << "destroying " << id;
    }

};



int main(){


    X a(1);
    a = X(2);


    while(true);
    return 0;

}

我得到以下输出:destroying 2

这完全出乎我的意料,因为我认为析构函数总是会在对象停止存在时被调用。

但在本例中,对象 1 停止存在并被对象 2 替换。但不是调用对象 1 的析构函数,而是调用对象 2 的析构函数。

谁能解释一下?

【问题讨论】:

  • a 仅在 main 返回后停止存在,在此期间它永远不会停止存在,您只能使用 op= 分配给它

标签: c++ destructor


【解决方案1】:

a = X(2); => 表达式调用赋值运算符和a.id 数据成员由temporaryobject.id 即2 初始化。

a = X(2); => 表达式调用编译器提供的默认赋值运算符并进行蜡样复制。

X(2) 表达式创建临时对象,temporaryobject.id 初始化为 2。

当临时对象被另一个对象调用时,第一次解构 get 调用。

【讨论】:

    【解决方案2】:

    在您的情况下,只有一个对象被销毁 - 即分配右侧的临时 X(2)。原始的X(1) 不会被破坏,因为它会被赋值覆盖。当它被销毁时,它也会打印destroying 2

    但是,修改后的X(2)(以X(1) 开头)通过无限循环保持活动状态,因此它也不会被破坏。删除无限循环可解决此问题 (demo)。

    【讨论】:

    • 这是一个很好的答案,但我只是在阅读@PlasmaHH 提到赋值运算符的评论后才理解它。我认为您也应该在回答中提及这一点;)因为首先,我认为(1)应该被破坏,然后它在内存中的空间应该被(2)的新副本填充。但相反的情况是,(1)只是被修改为匹配(2)
    • @VanCoding 我说了两次“赋值”,假设你知道它是一个运算符 :)
    • 我知道,但是分配可以得到不同的解释,如您所见:D 我认为内存已分配,而不是调用将 (1) 转换为 (2) 的函数
    猜你喜欢
    • 2011-07-19
    • 1970-01-01
    • 2017-11-18
    • 2017-05-27
    • 2021-07-19
    • 2014-05-03
    • 2010-10-31
    • 2016-02-03
    • 1970-01-01
    相关资源
    最近更新 更多