首先,如果知道一个函数不可能抛出异常,则应该将其声明为noexcept,以提高代码的运行效率,但是如果函数却违法声明抛出了异常将导致程序直接中止。
在C++98和C++11中都可以声明一个函数不会抛出异常,代码如下:
int f(int x) throw(); //f不会抛出异常,C++98风格
int f(int x) noexcept; //f不会抛出异常,C++11风格
而使用noexcept而非throw()好处有一下几个原因:
- 声明为nocept,优化器会对函数做最大值的优化,包括将执行器栈保持在可开解状态。
- C++11新增了移动语义,所以STL标准库也做了一次大的性能调整,即在原先赋值操作地方,将采用"能移动则移动,必须复制才复制"策略。而能否移动的一个关键点就是STL函数是否声明了noexcept。而STL函数是否声明noexcept,取决于STL容器所含自定义对象对应的函数是否声明了noexcept。例如:如果自定义对象的移动拷贝函数声明了noexcept,则在对该对象进行push_back后扩张时,将使用移动拷贝而非复制拷贝,又或者对某对象的swap()成员函数声明了noexcept,则容器在调用STL的swap()函数时,将使用移动拷贝。
- 默认的,所有内存释放函数(delete函数)或析构函数,无论是用户自定义还是编译器生成,都隐式的声明了noexcept。
要点速记
- noexcept声明是函数接口的组成部分,这意味着调用方可能对其有依赖
- 相对于不带nocept声明的函数,带nocept声明的函数有更多机会得到优化
- noexcept性质对移动操作、swap、内存释放函数、析构函数最有价值
- 大多数函数都是异常中立的,不具备noexcept性质