【发布时间】:2016-11-23 17:00:30
【问题描述】:
(我的问题的答案涉及复制构造函数,但是复制发生在从函数返回时,而不是在对另一个类的方法调用中。我实际上看到了引用的可能重复项,但没有从由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;
}
我得到这个输出:
幻影 1 构建。 幻影 2 构建。 幻影2被毁。 幻影2被毁。 Phantom 2 会说话。
让我困惑的是输出中的第四行。
输入main 时会自动构建幻影1。
输入getPhantom时会自动构建幻影2。
Phantom 2 在退出 getPhantom 时会自动销毁(这就是为什么我认为从 getPhantom 返回它是不安全的)。
但在那之后我很困惑。根据调试器,getPhantom 已经返回在第四行输出出现之前。第二次调用Phantom的析构函数时,调用栈是这样的:
主要 ~幻影
在托管语言中,我可以看到这一行:
phantom = getPhantom();
会破坏 Phantom 1,但不会触及 Phantom 2。这是 C++,而不是 Java。
是什么导致第二次调用 Phantom 2 的析构函数?
【问题讨论】:
-
任何时候你想计算构造函数/析构函数调用,你都需要记住打印出复制构造函数调用。
-
当然按值返回对象是安全的。否则,该语言将从根本上被破坏。
-
真的应该有一个FAQ关于如何正确计算构造函数和析构函数,这个问题不断出现。
-
Rule of three。服从!
-
@StevensMiller 是的。有复制省略和返回值优化之类的东西,但返回一些东西意味着你把它复制到函数返回空间中。
标签: c++ destructor automatic-storage