ScreenShot#1:示例(示例&){...)//没有使用“const”没有错误 ScreenShot#2:当不包含复制构造函数时,将调用析构函数两次。
当我在VC ++ 2010中运行此代码时,我发现结果令人惊讶,请看一下:
#include <iostream>
using namespace std;
class Sample {
public:
Sample() { cout<<"Sample().\n"; }
// Sample (Sample&) { cout<<"Sample(Sample&).\n"; }
~Sample() { cout<<"~Sample().\n"; }
};
void fx() {
throw Sample();
}
int _tmain(int argc, _TCHAR* argv[])
{
try { fx(); }
catch (Sample&) { cout<<"Caught Sample.\n"; }
return 0;
}
请告诉我为什么在示例中不包含copy-constructor,析构函数被调用两次。如果我们在析构函数中释放堆,那么这样会导致Abort()。
另外我知道对象的副本是由抛出对象创建的,但是为什么它没有为此调用copy-constructor。
请参阅随附的代码和输出屏幕截图。
答案 0 :(得分:2)
这似乎是VC ++编译器中的一个错误(功能?:))已经存在了一段时间(我没有任何链接直接支持这个语句,但我没有时间继续搜索。我想我自己也遇到过这一两次。)这仍然发生在VC ++ 2012中。
即使您不使用复制文件,也始终定义复制文件是一种很好的编码习惯。这是The Rule of Three的一部分。但有一些警告。
在投掷时尝试执行copy ctor时,VC ++将使用对象的上下文而不是调用者。因此,即使标记为私有,它仍然可以访问。这可能是遗留的事情,虽然我找不到任何具体的事实。
VC ++允许在投掷时使用非const参数复制ctor。这也是传统的,允许在实施移动范例之前转移资源。我只是发现了一些含糊不清的东西。不,VC ++似乎没有使用移动范例来抛出对象,所以如果你尝试实现移动构造函数,这仍然会发生。
有关移动构造函数的更多信息,您可以看到here。
请注意,微软似乎会根据它是否会破坏太多东西来挑选它将实施的C ++标准的哪一部分。出于这个原因,我认为我不想成为M $的编译器开发团队。 :/