在C ++ 11中,不推荐使用:
void foo() throw();
并替换为
void foo() noexcept;
在this article中解释说,其原因(其中包括归结为相同的事情)是
在运行时而不是在编译时检查C ++异常规范,因此它们不提供程序员保证已处理所有异常。
虽然这对我有意义,但我不明白为什么throw()
首先被动态检查,或者为什么noexcept
除了调用std::terminate
之外不提供异常保证而不是正常的堆栈展开(这实际上不是IMO的坚实保证)。
如果发生这种情况,是否有可能检查是否抛出异常 并且编译失败?我认为,基本上有三种情况:
void foo() noexcept
{
// 1. Trivial case
throw myexcept();
// 2. Try-catch case
// Necessary to check whether myexcept is derived
// from exception
try
{
throw myexcept();
}
catch(exception const & e)
{}
// 3. Nested function call
// Recursion necessary
bar();
}
对于每种类型实例化C ++中的模板,编译应用程序仍然需要永远 - 所以为什么不更改noexcept
以强制编译器检查在编译期间是否抛出异常?
我看到的唯一困难是函数可能会或可能不会根据运行时状态抛出 - 但在我看来,不应该允许该函数调用自己noexcept
。
我是否遗漏了某些内容,或者是不打算进一步增加编译时间,还是想让编译器开发人员轻松一点?
答案 0 :(得分:1)
我认为很多事情都归结为这样一个事实:当定义异常规范时,编译器编写者远远落后于功耗曲线。实现C ++ 98足够复杂,以至于只有一个编译器甚至声明来实现其所有功能。每个其他编译器都遗漏了标准中包含的至少一个主要功能。最公平地承认他们遗漏的远不止这些。
您还需要记住,动态异常规范也比throw()
复杂得多。它允许程序员指定可以抛出的任意类型集。更糟糕的是,指定一个函数可以抛出foo
意味着它也可以抛出从foo
派生的任何东西。
可以静态执行异常规范,但显然会增加相当多的额外工作,没有人真正确定它会提供什么(如果有的话)好处。在这种情况下,我认为大多数人认为静态执行是后来可能需要的东西,如果似乎有足够的用来证明工作是合理的话。从在运行时强制执行到编译时,不需要修改现有代码,只需修改现有实现。
另一点是,我不确定是否真的强烈支持异常规范。我认为基本的想法已得到普遍认同,但是当你深入了解它时,可能更少关于细节。
结论:很容易强制执行动态执行,并在以后留下静态执行(如果有的话)。事实证明,在任何情况下,静态执行可能都不会真正增加所有积极性,因此强制执行它可能无论如何都不会取得多大成就。