noexcept是C++11引入的关键字,用于声明函数不抛异常,违反承诺将调用std::terminate;它影响编译器优化、标准库行为(如移动操作选择)、函数类型签名,并支持编译期异常检查。
noexcept 是 C++11 引入的关键字,用来显式声明一个函数**不会抛出任何异常**。
它既是编译器的承诺,也是调用者的契约——一旦标记为 noexcept,函数体内若意外抛出异常(且未被捕获),程序将立即调用 std::terminate() 终止执行,而不是尝试栈展开。
它不只是“说明不抛异常”,更直接影响编译器行为和标准库决策:
std::vector::resize() 在重新分配内存时,若元素类型的移动构造函数是 noexcept,就会优先选择移动而非复制,显著提升性能;否则可能退化为复制以维持异常安全。void f() noexcept 和 void f() 是两种不同的函数类型,不能相互赋值或重载(除非仅 noexcept 性质不同,C++17 起允许这种重载)。noexcept 运算符判断:可用 noexcept(expr) 在编译期检查某表达式是否不抛异常,常用于模板 SFINAE 或 constexpr if 分支。基本形式:void func() noexcept; 表示硬性承诺不抛异常。
更灵活的是带条件表达式的写法:void func() noexcept(noexcept(other_func()));
noexcept(...) 是运算符,返回 bool 编译期常量。noexcept,取决于 other_func() 是否 noexcept”。这是实现“异常中立”(exception-neutral)接口的关键技巧。MyContainer(MyContainer&& rhs) noexcept(noexcept(std::declval().move())) 。它不提供运行时保护,也不自动让函数变安全:
noexcept 函数仍可调用会抛异常的函数——只要你在内部捕获了它们;否则直接终止程序。noexcept(true)(C++11 起),所以务必确保析构中不抛异常,或显式写成 ~T() noexcept(false)(极少需要)。noexcept。违反承诺的代价是静默崩溃(std::terminate),比异常更难调试。C++ 社区通常把异常安全分为三类:
比如 std::swap、std::unique_ptr 的移动操作都要求 noexcept,否则容器在异常场景下无法保证强安全。
基本上就这些。noexcept 不复杂但容易忽略,关键是把它当作接口契约来设计,而不是事后补的性能标签。