noexcept说明符与noexcept运算符详解
请详细解释 C++11 引入的 noexcept 关键字:noexcept 说明符(作为函数修饰符)和 noexcept 运算符(编译期检查)的区别,以及 noexcept 对移动语义、容器性能的影响。
回答
我是大山
noexcept 说明符:声明函数不抛出异常。
void func() noexcept; // 不抛出
void func() noexcept(true); // 同上
void func() noexcept(false); // 可能抛出
void func() noexcept(noexcept(...)); // 条件 noexcept
noexcept 运算符:编译期检查表达式是否被标记 noexcept。
template<typename T>
void swap(T& a, T& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
对性能/移动语义的影响:
- 容器优化:
std::vector在重新分配时使用std::move_if_noexcept——若移动操作是 noexcept 则移动元素,否则拷贝元素以提供强异常安全保证。未标记 noexcept 的移动构造函数会退化为拷贝,性能骤降(O(n)分配)。 - 代码生成:noexcept 函数生成更小的异常处理代码,编译器可更好地优化。
- 析构函数:C++11 开始默认为 noexcept。
最佳实践:移动构造函数和移动赋值应标记 noexcept。不会抛出的函数(如 getter、数学计算)也应标记 noexcept。