我有以下代码:
#include <stdio.h>
class Foo {
public:
int a;
~Foo() { printf("Goodbye %d\n", a); }
};
Foo newObj() {
Foo obj;
return obj;
}
int main() {
Foo bar = newObj();
bar.a = 5;
bar = newObj();
}
当我用 g++
编译并运行它时,我得到:
Goodbye 32765
Goodbye 32765
打印的数字似乎是随机的。
我有两个问题:
- 为什么析构函数被调用两次?
- 为什么不是第一次打印
5
?
我有 C 语言背景,因此有 printf
,但我在理解析构函数、何时调用它们以及如何从函数返回类方面遇到困难。
最佳答案
让我们看看在您的主函数中发生了什么:
int main() {
Foo bar = newObj();
这里我们只是实例化一个Foo
,并用newObj()
的返回值初始化它。由于copy elision,这里没有调用析构函数: 很快总结一下,obj
不是复制/移动 obj
到 bar
然后销毁 obj
,obj
是直接在 bar
的存储中构建。
bar.a = 5;
这里没什么好说的。我们只需将 bar.a
的值更改为 5。
bar = newObj();
这里bar
是copy-assigned1newObj()
的返回值,然后析构这个函数调用创建的临时对象2,这是第一个再见
。此时 bar.a
不再是 5
而是临时对象的 a
中的任何内容。
}
main()
结束,局部变量被析构,包括bar
,这是第二个Goodbye
,不打印5
因为之前的分配。
1 由于用户定义的析构函数,这里没有发生移动赋值,没有隐式声明移动赋值运算符。
2 正如 YSC 在评论中提到的,请注意此析构函数调用具有未定义的行为,因为它正在访问此时未初始化的 a
。 bar
与临时对象的分配,特别是 a
作为其一部分的分配,出于同样的原因也具有未定义的行为。
关于c++ - 函数返回的类的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56592055/