class A
{
public:
~A();
};
A::~A()
{
std::cout<<"Destructor!!!\n"<<std::endl;
std::exception e;
throw e;
}
void main()
{
try
{
A a;
//A a1,a2;//This gives out two lines of "Destructor!!!" then the program terminates
}
catch(std::exception)
{
std::cout<<"Caught!!!\n"<<std::endl;
}
}
我知道在析构函数中发出异常是一种不好的做法。但它不违法。
上面的程序进入catch块。似乎try
块正在防止局部变量的破坏。
但是,如果我取消注释代码,它会给出不同的东西。在这种情况下,似乎没有处理第一个异常,并且终止是由多个异常引起的。
现在我不确定在激励功能时是否会破坏局部变量。我使用的是VS2005 btw。
答案 0 :(得分:3)
try
/ catch
块只会处理一个例外。如果在块中构造了两个或多个类型为A
的对象,则每个对象的析构函数都将抛出异常。抛出的第一个异常(从最后创建的对象/先破坏的)可以得到处理。但是,在到达处理程序之前,将销毁所有其他本地对象。当块中有另一个A
对象时,它也会被销毁,抛出异常,瞧,有两个例外。当析构函数外有两个未处理的异常时,系统会调用需要终止程序的std::terminate()
。
使用C ++ 11,所有析构函数都被隐式定义为noexcept
或noexcept(true)
(两者都是等价的)。这种改变的原因是默认情况下构建和销毁临时移动应该是noexcept
。如果你想用C ++ 11抛出析构函数,你需要将析构函数声明为noexcept(false)
,例如:
class A {
public:
~A() noexcept(false) { throw std::exception(); } // still a Bad Idea!!!
// ...
};
当从析构函数中抛出异常时,您实际上需要确保在处理现有异常时,对象不会因为堆栈展开而被销毁。在析构函数中,只要没有异常逃避析构函数,就可以有异常。
实际上,没有安全的方法来了解对象是否因堆栈展开而被销毁。虽然从语言的角度来看是合法的,但最好不要从析构函数中抛出。