EMCPP条款14:只要函数不会发射异常,就为其加上 noexcept 声明
考虑一个函数 f
,欲向调用方保证它们不会接收到异常。两种表达方式如下:
1 | int f(int x) throw(); // no exceptions from f: C++98 style |
如果,在运行期,一个异常逸出 f
的作用域,则 f
的异常规格袚违反。在 C++98 异常规格下,调用栈会开解至 f
的调用方,然后执行了一些与本条款无关的动作以后,程序执行中止。而在 C++11 异常规格下,运行期行为会稍有不同:程序执行中止之前,栈只是可能会开解。
开解调用栈,和可能开解调用栈,这一点点区别对于代码生成造成的影响之大可能出乎人们的意料。在带有 noexcept
声明的函数中,优化器不需要在异常传出函数的前提下,将执行期栈保持在可开解状态;也不需要在异常溢出函数的前提下,保证所有其中的对象以其被构造顺序的逆序完成析构。而那些以 throw()
异常规格声明的函数就享受不到这样的优化灵活性,和没有加异常规格声明的函数一样。这些可以总结为下述情况:
1 | RetType function(params) noexcept; // most optimizable |
仅仅这个就已经构成充分理由,让你给任何已知不会产生异常的函数加上 noexcept
声明了。
这个条款目前不太理解,等以后补全相关知识后会再更新
要点速记
noexcept
声明是函数接口的组成部分,这意味着调用方可能会对它有依赖 。- 相对于不带
noexcept
声明的函数,带有noexcept
声明的函数有更多机会得到优化 。 noexcept
性质对于移动操作、 swap、函数释放函数和析构函数最有价值。- 大多数函数都是异常中立的,不具各
noexcept
性质。