构造函数使用异常处理代码表现得很奇怪

时间:2013-03-11 04:41:45

标签: c++ visual-c++ exception-handling constructor

ScreenShot#1:示例(示例&){...)//没有使用“const”没有错误 enter image description here ScreenShot#2:当不包含复制构造函数时,将调用析构函数两次。 enter image description here

当我在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。

请参阅随附的代码和输出屏幕截图。

1 个答案:

答案 0 :(得分:2)

这似乎是VC ++编译器中的一个错误(功能?:))已经存在了一段时间(我没有任何链接直接支持这个语句,但我没有时间继续搜索。我想我自己也遇到过这一两次。)这仍然发生在VC ++ 2012中。

即使您不使用复制文件,也始终定义复制文件是一种很好的编码习惯。这是The Rule of Three的一部分。但有一些警告。

  1. 在投掷时尝试执行copy ctor时,VC ++将使用对象的上下文而不是调用者。因此,即使标记为私有,它仍然可以访问。这可能是遗留的事情,虽然我找不到任何具体的事实。

  2. VC ++允许在投掷时使用非const参数复制ctor。这也是传统的,允许在实施移动范例之前转移资源。我只是发现了一些含糊不清的东西。不,VC ++似乎没有使用移动范例来抛出对象,所以如果你尝试实现移动构造函数,这仍然会发生。

  3. 有关移动构造函数的更多信息,您可以看到here

    请注意,微软似乎会根据它是否会破坏太多东西来挑选它将实施的C ++标准的哪一部分。出于这个原因,我认为我不想成为M $的编译器开发团队。 :/