C++ throw() 优化

5
根据优化C ++
对于您确定永远不会抛出异常的函数,请使用空异常规范(即在声明中添加throw())。
如果我知道90%的方法不会引发异常怎么办? 为所有这些方法附加throw()似乎是不常规且啰嗦的。 如果没有,有什么优点吗? 或者我理解错了什么?

应用 nothrow 会在编译时检测到可能的违规吗?(只是为了确保100%) - πάντα ῥεῖ
你是否有充分的理由和一个能够胜任的代码库来使用异常,或者你只是因为相信它们默认情况下是好的并且始终有效而使用它们? - user2485710
除了你知道在代码中是瓶颈的函数之外,不必担心它。 - Mark Ransom
现在有点过时了,但是:http://www.gotw.ca/publications/mill22.htm - Fred Larson
有什么优点吗?你读了你链接的文章吗?整个重点是讨论这些优化的优点。你手动编译代码吗?如果没有,你写了一个可以读取你思想的编译器吗?如果没有,你到底希望编译器如何获取90%的函数不会抛出异常的信息?是的,它很冗长,但这是为了提取额外的优化而付出的代价。如果你不关心优化,就别费心了。 - iheanyi
顺便提一句,不抛出异常意味着除了函数本身不会抛出异常之外,它们也不会调用任何可能会抛出异常的代码或可能调用可能会抛出异常的代码(等等)。 - iheanyi
2个回答

9
C++11引入了noexceptthrow有点过时(根据this效率较低)。

noexceptthrow()的改进版,在C++11中throw()已经过时。与throw()不同,noexcept不会调用std::unexpected,可能会或可能不会解开堆栈,这潜在地允许编译器在没有throw()运行时开销的情况下实现noexcept

当违反空抛出规范时,程序将终止;这意味着只有在函数具有无抛出异常保证时才声明函数为非抛出异常。

最后,您需要一个移动构造函数来使其非抛出异常(使用noexcept指定),以便能够使用std::vector<T>::push_back的r-value ref版本(请参见更好的说明here)。


5
标准的 throw() 不会增强可优化性。
如果一个方法被标记为 throw(),那么编译器会强制检查方法是否抛出异常并展开堆栈——就像没有标记为 throw() 的函数一样。唯一的区别在于,对于标记为 throw() 的函数,当异常离开函数时,全局的 unexpected_handler 会被调用(通常会调用 terminate()),将堆栈展开到该级别,而不是处理异常的普通函数的行为中,在没有异常说明的情况下正常处理异常。
对于 C++11 之前的代码,Sutter & Alexandrescu 在《C++ 编程规范》中建议:
避免使用异常说明。
反对这些说明:除非强制使用(因为其他无法更改的代码已经引入了它们;请参阅 Exceptions),否则不要在函数上写异常说明。
普遍但仍然不正确的信念是,异常说明静态地保证函数只会抛出列出的异常(可能没有任何异常),并基于此知识启用编译器优化。
实际上,异常说明实际上稍微有点不同:它们导致编译器在函数体周围注入额外的运行时开销,以通过运行时检查来强制执行函数实际上只发出列出的异常(可能没有任何异常),除非编译器可以静态证明异常说明永远不会被违反,在这种情况下,它可以自由地优化检查。而异常说明可能会启用和防止进一步的编译器优化(除了已经描述的固有开销);例如,一些编译器拒绝内联带有异常说明的函数。
请注意,在某些版本的 Microsoft 编译器中(我不确定这个行为在更近期的版本中是否已更改,但我不认为如此),throw() 的处理方式是非标准的。 throw() 等同于 __declspec(nothrow),它允许编译器假定函数不会抛出异常,如果抛出异常则会导致未定义的行为。
C++11 废弃了 C++98 风格的异常说明,并引入了 noexcept 关键字。Bjarne Stroustup 的 C++11 FAQ 对此有以下解释:
如果声明为 noexcept 的函数抛出异常(因此异常试图逃逸,则为 noexcept 函数),程序将终止(调用 terminate())。terminate() 的调用不能依赖于对象处于良好定义状态(即不存在保证已调用析构函数、无保证的堆栈展开,并且没有可能使程序恢复到没有遇到问题的状态)。这是有意的,并使 noexcept 成为一种简单、粗糙且非常有效的机制(比旧的动态 throw() 机制效率高得多)。
在C++11中,如果从标记为noexcept的函数抛出异常,则编译器不必完全展开堆栈。这提供了一些优化可能性。Scott Meyers在他即将出版的书“Effective Modern C ++”中讨论了新的noexcept

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接