从C++11开始,咱们能看到不少代码当中都有关键字noexcept。好比下面就是std::initializer_list
constexpr initializer_list() noexcept : _M_array(0), _M_len(0) { }
该关键字告诉编译器,函数中不会发生异常,这有利于编译器对程序作更多的优化。
若是在运行时,noexecpt函数向外抛出了异常(若是函数内部捕捉了异常并完成处理,这种状况不算抛出异常),程序会直接终止,调用std::terminate()函数,该函数内部会调用std::abort()终止程序。优化
C++中的异常处理是在运行时而不是编译时检测的。为了实现运行时检测,编译器建立额外的代码,然而这会妨碍程序优化。
在实践中,通常两种异常抛出方式是经常使用的:this
后面这一种方式中在以往的C++版本中经常使用throw()表示,在C++ 11中已经被noexcept代替。code
void swap(Type& x, Type& y) throw() //C++11以前 { x.swap(y); } void swap(Type& x, Type& y) noexcept //C++11 { x.swap(y); }
在第2节中单独使用noexcept,表示其所限定的swap函数绝对不发生异常。然而,使用方式能够更加灵活,代表在必定条件下不发生异常。ci
void swap(Type& x, Type& y) noexcept(noexcept(x.swap(y))) //C++11 { x.swap(y); }
它表示,若是操做x.swap(y)不发生异常,那么函数swap(Type& x, Type& y)必定不发生异常。编译器
一个更好的示例是std::pair中的移动分配函数(move assignment),它代表,若是类型T1和T2的移动分配(move assign)过程当中不发生异常,那么该移动构造函数就不会发生异常。it
pair& operator=(pair&& __p) noexcept(__and_<is_nothrow_move_assignable<_T1>, is_nothrow_move_assignable<_T2>>::value) { first = std::forward<first_type>(__p.first); second = std::forward<second_type>(__p.second); return *this; }
使用noexcept代表函数或操做不会发生异常,会给编译器更大的优化空间。然而,并非加上noexcept就能提升效率,步子迈大了也容易扯着蛋。
如下情形鼓励使用noexcept:io
struct X { ~X() { }; }; int main() { X x; // This will not fire even in GCC 4.7.2 if the destructor is // explicitly marked as noexcept(true) static_assert(noexcept(x.~X()), "Ouch!"); }
最后强调一句,在不是以上状况或者没把握的状况下,不要轻易使用noexception。编译