为什么析构函数会被调用三次?

5

输入:

#include <iostream>
using namespace std;
class SimpleClass
{
    public:

    SimpleClass()
    {
        cout<<"SimpleClass Constructor\n";
    }
    virtual ~SimpleClass()
    {
        cout<<"SimpleClass destructor\n";
    }
};
int main()
{
    SimpleClass a;    
    SimpleClass lol = a;

    SimpleClass b;
    SimpleClass * lol2 = &b;
}

输出:

SimpleClass Constructor
SimpleClass Constructor
SimpleClass destructor
SimpleClass destructor
SimpleClass destructor

我很困惑为什么析构函数被调用了3次。

构造函数只被调用了两次!!!


4
你有三个对象,对吗?a, lol, b。你预计会有多少次析构函数调用?如果你实现了“拷贝构造函数”,你将会看到其中一个对象被复制了。 - billz
你期望它发生多少次? - tenfour
我期望了两次。因为lol构造函数没有被调用。 - Mathew Kurian
3
为什么只有两个对构造函数的调用? - Cogwheel
3
不,"copy constructor" 被调用了,用于创建 lol 的副本。 - Jonathon Reinhart
7个回答

11
析构函数被调用了三次,分别是 alolb
在您的情况下,ab 是使用 默认构造函数 实例化的。但请注意,lol 是使用 复制构造函数 实例化的。

6
因为恰好创建了3个SimpleClass类的对象,但是你的构造函数只被调用了2次:
  • 第一个对象是 a,调用了你的构造函数;
  • 第二个对象是 lol,通过隐式定义的复制构造函数a中初始化(因此绕过了你的构造函数);
  • 第三个对象是 b,调用了你的构造函数。

请注意,lol2只是指向b的指针,因此不会进行额外的调用。

而正确的名称是“析构函数”,而非“deconstructor” ;)


你能重载这个隐式定义的复制构造函数吗? - Mathew Kurian
是的,你可以明确地定义它为SimpleClass(const SimpleClass& other)。但这里有一个警告:当安全时,编译器允许优化掉调用。这就是为什么复制构造函数通常不应该有任何副作用(写入cout是一个副作用)。如果你的复制构造函数没有输出任何内容,请关闭编译器优化。 - Alex Jenter
1
@AlexJenter:但如果复制构造函数调用被优化掉了(在这种情况下不会),析构函数也将被优化掉,因此构造函数调用仍然等于析构函数调用。 - Benjamin Lindley
@Benjamin Lindley:没错,谢谢你的有用补充。我并不是指这个例子会被优化,而是一般性地提醒这是可能的。 - Alex Jenter

5

你有三个对象 alolb。你没有跟踪编译器生成的复制构造函数(这个被 lol 调用),所以只有两个构造函数。


3

每个变量 a, lol, 和 b 都会被调用一次。

为了确认这点,您可以在类中添加一个字段,并为每个变量分配一个名称/ID,在析构函数中打印出来。您还可以打印出指向该对象的指针 this 的值。


2
  SimpleClass lol = a;    //calls the default copy constructor which you have not defined

如果重写了复制构造函数,那么您可能会看到一个新的构造函数被调用。


0

你有 alolb

也许你可以在 main() 函数中打印它们的地址,并在构造函数和析构函数中也打印它们的地址,这样你就可以看到它们了。


0

因为析构函数对于所有对象都是相同的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接