【发布时间】:2012-09-26 05:10:15
【问题描述】:
作为学习练习,以下代码在 Visual Studio 2012 Express for Windows Desktop 中编译和运行。
#include <cstdio>
class X
{
public:
X() { printf("default constructed\n"); }
~X() { printf("destructed\n");}
X(const X&) { printf("copy constructed\n"); }
X(X&&) { printf("move constructed\n"); }
X & operator= (const X &) { printf("copy assignment operator\n"); }
};
X A() {
X x;
return x;
}
int main() {
{
A();
}
std::getchar();
}
在禁用编译器优化 (/Od) 的情况下编译时,结果输出表明析构函数被调用了两次。这是一个问题,因为只构造了一个对象。 为什么要调用两次析构函数?如果该类管理自己的资源,这不是问题吗?
default constructed
move constructed
destructed
destructed <<< Unexpected call
我尝试了几个实验来尝试解释输出,但最终这些并没有导致任何有用的解释。
实验 1:在启用优化(/O1 或 /O2)的情况下编译相同的代码时,结果输出为:
default constructed
destructed
这表明命名返回值优化已经省略了对移动构造函数的调用,并掩盖了潜在的问题。
实验 2:禁用优化并注释掉移动构造函数。生成的输出符合我的预期。
default constructed
copy constructed
destructed
destructed
【问题讨论】:
-
你的构造函数和析构函数的数量一样,所以没有问题。它被移动形式的事实是不相关的。对于管理资源的类来说,这不是问题,他们都知道事情就是这样工作的。
标签: c++ visual-c++ c++11 visual-studio-2012 move-semantics