当抛出异常但未被捕获时,堆栈展开。这意味着将调用析构函数,一切都将被很好地清理。但是考虑一下:
foo::~foo()
{
bar();
}
foo
如果我们因为一个未捕获的异常而到达析构函数,并且bar();
碰巧抛出,应用程序将立即终止,因为 C++ 一次不能处理多个异常。
如果我们例如吞下异常,则不会发生这种情况:
foo::~foo()
{
try { bar(); } catch(...) { /* nom nom */ }
}
更新:
第一部分指的是这样的异常规范:
struct foo
{
void bar() throw();
}
本规范的有效语法是
throw() // does not throw any exception
throw( list of exceptions ) // may throw one of these exceptions
throw(...) // may throw any exception
但正如罗德里戈所说,这被证明是一个坏主意,因为这些规范导致动态检查(在运行时)是否引发异常,从而显着降低性能。
在 C++11 中,它被noexcept
关键字替换:
noexcept(true)
noexcept(false)
noexcept // identical to noexcept(true)
这是您向编译器提供的保证,而不是相反。
但现在终于回答你的问题了。当您throw
在某个嵌套链中给出异常规范,并且在深度嵌套的函数中抛出异常时,您将不得不在此过程中更新每个函数的签名。异常规范愚蠢且不应再使用的另一个很好的理由。