noexcept 是自 C++11 引入的新特性,指定函数是否可能会引发异常,以下是 noexcept 的标准语法:
noexcept-expression:
noexcept
noexcept(** *constant-expression* **)
constant-expression 是一个 bool 类型的常量表达式,是一种异常规范(exception specification),属于C++的语言特性,表示是否会发生异常。
noexcept 等效于 noexcept(true)。
noexcept(true) 或者 noexcept 表示函数不会抛出或者传递异常,如果函数发生异常,将调用 std::terminate 立即终止程序。
noexcept(false) or 或者不使用 noexcept (析构函数或释放函数默认声明为 noexcept), 表示函数所有可能的异常都会被抛出.
建议将所有不会抛出异常(包括以后)的函数声明为 noexcept。
当函数声明为 noexcept 后,编译器能够在一些不同的上下文环境中产生更加高效的代码。
函数可以标记为 noexcept 当且仅当内部调用的所有函数也都直接或者间接的标记为 noexcept 或者 const。
编译器没有义务检查所有层级代码是否会抛出异常到 noexcept 函数。
如果标记了 noexcept 的函数确实抛出了异常,那么std::terminate将会被立即调用,并且不能保证函数内部的对象能够被析构。
比起优化,正确性更为重要。
当你在最开始声明一个函数为 noexcept, 而后又反悔想要去掉 noexcept 标记,那么你将会影响到调用端的代码。
下面的函数被标记为有条件的 noexcept:函数是否为 noexcept 取决于 noexcept 的子句表达式是否为 noexcept。
例如,有两个包含 Widget 对象的数组,交换两个数组的函数是否为 noexcept 取决于 交换两个数组中元素的函数是否为 noexcept,即,交换两个 Widget 对象是否为 noexcept。
因此 Widget 对象 swap 的实现决定了 Widget 数组的交换函数是否为 noexcept。
同样地,包含 Widgets 的 std::pair 对象的交换函数是否应该为 noexcept 取决于交换两个 Widget 对象是否为 noexcept。
上层的数据结构操作可以为 noexcept 仅当下层的数据结构操作为 noexcept。这就促使你,只要允许,就尽可能地提供 noexcept 的函数。
template <class T, size_t N>
void swap(T (&a)[N], T (&b)[N]) noexcept(noexcept(swap(*a, *b)));
template <class T1, class T2>
struct pair {
…
void swap(pair& p) noexcept(noexcept(swap(first, p.first)) && noexcept(swap(second, p.second)));
…
};
noexcept 是函数接口的一部分,这意味着调用者会依赖它。noexcept 函数可优化性要高于 non-noexcept 函数。noexcept 用在数据移动,交换,内存释放函数,析构函数中会更有价值。non-noexcept 的。在 C++17 之前还有一种异常规范 (dynamic exception pecification) throw(optional_type_list)。
C++17 之后 throw(optional_type_list) 已被移除(除了 throw()),throw() 等同于 noexcept。
应该避免使用 throw(optional_type_list) 或者 throw()。
原文:https://www.cnblogs.com/Steven-HU/p/14384854.html