析构函数抛出异常

St.*_*rio 0 c++ destructor

我试图理解为什么析构函数抛出异常是一个非常糟糕的主意.通过谷歌搜索,我理解如果析构函数抛出,比如说,在块范围对象的销毁过程中,对象的销毁停止了,如果其他对象析构函数没有调用则会导致内存泄漏.

但就其本身而言,析构函数抛出异常是如此糟糕?例如(完整示例):

struct A
{
    int a;
    char b;
    A() : a(10), b('a') { }
    ~A(){ throw std::exception(); }
};

int main()
{
    A a; //destructor throws, but there're no more objects to destruction 
         //therefore I think there's no memory leak
}
Run Code Online (Sandbox Code Playgroud)

我们在上面的程序中得到了UB吗?

tws*_*aef 5

在这个简单的例子中,抛出了bar()中的异常并且展开了堆栈,破坏了a,这会引发另一个异常.在这种情况下可以抛出哪个异常?

struct A
{
    int a;
    char b;
    A() : a(10), b('a') { }
    ~A(){ throw std::exception(); }
};
void bar () 
{
    A a;
    throw std::exception();
}
int main()
{
    bar();
}
Run Code Online (Sandbox Code Playgroud)

来自C++ FAQ

在堆栈展开期间,所有这些堆栈帧中的所有本地对象都被破坏.如果其中一个析构函数抛出一个异常(比如它抛出一个Bar对象),那么C++运行时系统就处于一个不可取的情况:它应该忽略Bar并最终进入} catch(Foo e){它最初的位置何去何从?它应该忽略Foo并寻找一个} catch(Bar e){handler?没有好的答案 - 任何一种选择都会丢失信息.

所以C++语言保证它会在此时调用terminate(),而terminate()会终止进程.