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(...)
{}
}
输出是: 不能抛出
我错过了什么吗?由于
答案 0 :(得分:3)
这正是他的意思:“将不会抛出”意味着“不会抛出,因为它会认为在当前情况下投掷是不安全的”(不“会崩溃”;失败在这里意味着不会发生)。因为析构函数被调用作为异常std::uncaught_exception()
引起的堆栈展开的一部分返回true,而T::~T()
不使用可能抛出的代码(用他的话说: {{1将无法使用“可以抛出”的路径,即使它可以安全地),因为它认为它不应该抛出。关键是,因为T::~T
包裹在T
块中,所以即使存在待处理的异常,也可以安全地抛出。