为什么不能在dtor中使用uncaught_exception?

时间:2011-01-07 09:34:21

标签: c++ exception-handling

Herb Sutter在他的文章http://www.gotw.ca/gotw/047.htm中 指出我们不能在desturctor函数中使用uncaught_exception,

//  Why the wrong solution is wrong
//
U::~U() {
  try {
    T t;
    // do work
  } catch( ... ) {
    // clean up
  }
}

如果U对象由于在异常传播期间的堆栈展开而被销毁,则T ::〜T将无法使用“可抛出的代码”路径,即使它可以安全地进行。

但是我写了一个测试程序,而T ::〜T实际上并没有使用“可以抛出的代码”

#include <exception>
#include <iostream>
using namespace std;

class T {
  public:
  ~T() {
  if( !std::uncaught_exception() )
  {
    cout<<"can throw"<<endl;
    throw 1;
  } else
  {
    cout<<"cannot throw"<<endl; 
  }
}


};

struct U
{
~U() {
  try 
  {
    T t;
  }
  catch( ... ) 
  {
  }
}
};

void f()
{
  U u;
  throw 2;
} 

int main()
{
    try
    {
      f();
    }
    catch(...)
    {}
}

输出是: 不能抛出

我错过了什么吗?

由于

1 个答案:

答案 0 :(得分:3)

这正是他的意思:“将不会抛出”意味着“不会抛出,因为它会认为在当前情况下投掷是不安全的”(“会崩溃”;失败在这里意味着不会发生)。因为析构函数被调用作为异常std::uncaught_exception()引起的堆栈展开的一部分返回true,而T::~T()不使用可能抛出的代码(用他的话说: {{1将无法使用“可以抛出”的路径,即使它可以安全地),因为它认为它不应该抛出。关键是,因为T::~T包裹在T中,所以即使存在待处理的异常,也可以安全地抛出