c++ - 为什么自动对象的析构函数被调用两次?

标签 c++ destructor automatic-storage

(我的问题的答案涉及复制构造函数,但复制发生在从函数返回时,而不是在对另一个类的方法调用中。我实际上看到了引用的可能重复项,但没有从vector::push_back 我的函数在这里也做了一个拷贝。也许我应该有。)

我想了解自动对象的构造/破坏。我遇到了一些对我来说可疑的代码,所以我编写了自己的版本以努力理解它。简而言之,原始代码包含一个返回函数本地对象(自动对象)的函数。这对我来说看起来不安全,所以我编写了这个程序来探索它:

#include <stdio.h>

class Phantom
{
private:
    static int counter;
    int id;

public:
    Phantom()
    {
        ++counter;
        id = counter;
        printf("Phantom %d constructed.\n", id);
    };

    virtual ~Phantom()
    {
        printf("Phantom %d destructed.\n", id);
    };

    void speak()
    {
        printf("Phantom %d speaks.\n", id);
    };
};

int Phantom::counter = 0;

Phantom getPhantom()
{
    Phantom autoPhantom;

    return autoPhantom; // THIS CAN'T BE SAFE
}

int main()
{
    Phantom phantom;

    phantom = getPhantom();

    phantom.speak();

    return 0;
}

我得到这个输出:

Phantom 1 constructed.
Phantom 2 constructed.
Phantom 2 destructed.
Phantom 2 destructed.
Phantom 2 speaks.

It's the fourth line in the output that confuses me.

Phantom 1 is constructed automatically when main is entered.

Phantom 2 is constructed automatically when getPhantom is entered.

Phantom 2 is destructed automatically when getPhantom is exited (which is why I believe returning it from getPhantom is unsafe).

But after that I'm confused. According to the debugger, getPhantom has returned before the fourth line of output appears. When Phantom's destructor is called the second time, the call stack is this:

main
~Phantom

In a managed language, I could see how this line:

phantom = getPhantom();

会破坏 Phantom 1,但不会影响 Phantom 2。这是 C++,不是 Java。

是什么导致第二次调用 Phantom 2 的析构函数?

最佳答案

您返回一份拷贝。因此 getPhantom() 中的变量在作用域的末尾被销毁,你留下它的拷贝也有 id 2。这是因为在返回时它调用复制构造函数(也是默认的)不会增加 id。

关于c++ - 为什么自动对象的析构函数被调用两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38481573/

相关文章:

C# 析构函数未按预期工作

c# - .NET 中的 C# 类何时调用析构函数?

c - 在应该释放其内存后访问可变长度数组

reference - C++/CLI 引用未在随后进入本地 block 时初始化为 nullptr

c - 返回指向自动变量的指针的函数

c++ - 如何指定工厂对象的类型

c++ - 对静态类成员的 undefined reference

C++ 子类的类型是否与它们自己及其父类相同?

c# - 析构函数 - 如果应用程序崩溃,它会被调用吗

c++ - std::map::find(char*) 在 Debug模式下无法在 64 位机器上运行