c++ noexcept关键字

发布于:2025-06-26 ⋅ 阅读:(13) ⋅ 点赞:(0)

noexcept 是 C++11 中引入的一个关键字,用来标记函数声明,表示该函数不会抛出异常。它可以用于函数、函数指针、Lambda 表达式等。使用 noexcept 可以帮助编译器进行优化,提高代码的执行效率,并且让程序在处理异常时更加明确。

1. 基本语法

void foo() noexcept {
    // 这个函数不会抛出异常
}

void bar() {
    // 这个函数可能会抛出异常
}

2. 作用

  • 提高性能:编译器知道一个函数不会抛出异常后,可以进行更多的优化(例如:不需要为异常处理创建额外的代码路径)。
  • 异常安全性:显式地声明一个函数不会抛出异常,可以使代码的异常行为更清晰,增强代码的可维护性。
  • 条件约束:可以用 noexcept 来限制函数的使用。例如,标准库中的 std::vector::swap 如果是 noexcept,那么它可以在 std::vector 中进行更多的优化。

3. 如何使用

标记函数:
使用 noexcept 修饰符来指示函数不抛出异常:

void foo() noexcept {
    // 函数实现
}

推断函数是否 noexcept:
C++11 中还引入了 noexcept 运算符,用来推断某个函数是否会抛出异常。

template<typename T>
void func(T&& arg) noexcept(noexcept(T(std::forward<T>(arg)))) {
    // 根据类型 T 的构造函数是否 noexcept 来决定是否 noexcept
}

4. noexcept 运算符

C++11 引入了 noexcept 运算符,可以用来检查某个表达式或类型是否会抛出异常:

template <typename T>
void check_if_noexcept() {
    if constexpr (noexcept(T())) {
        std::cout << "T() is noexcept\n";
    } else {
        std::cout << "T() is not noexcept\n";
    }
}

5. noexcept 与异常的关系

  • 如果你声明一个函数为 noexcept,但该函数抛出了异常,程序将调用 std::terminate(),从而导致程序终止。这是因为 noexcept 函数承诺不会抛出异常,违背这一承诺会导致程序的未定义行为。
  • 函数的 noexcept 状态可以通过以下规则推断:
  • 如果函数体内包含任何可能抛出异常的操作,则该函数不应标记为 noexcept。
  • 如果函数内部明确声明不抛出异常,例如函数内部只调用其他 noexcept 函数,则该函数可以标记为 noexcept。

6. 示例代码

#include <iostream>

void foo() noexcept {
    std::cout << "foo is noexcept\n";
}

void bar() {
    throw std::runtime_error("bar throws exception");
}

int main() {
    foo();  // No exception, works fine
    try {
        bar();  // Throws exception, catch it
    } catch (const std::exception& e) {
        std::cout << e.what() << std::endl;
    }
    
    return 0;
}

7. noexcept 和 Lambda 表达式

C++11 允许你在 Lambda 表达式中使用 noexcept:

auto lambda = []() noexcept { std::cout << "This is noexcept lambda\n"; };
lambda();

8. 注意事项

  • 默认情况下,函数不抛出异常:在 C++11 之前,函数没有明确标记为 noexcept,默认认为它可能会抛出异常。
  • 函数指针与 noexcept:如果一个函数指针指向的函数被标记为 noexcept,你也需要明确声明函数指针为 noexcept:
void (*fp)() noexcept = foo;

总结

  • noexcept 是 C++11 提供的一个关键字,标记函数不会抛出异常。
  • 它可以帮助编译器进行性能优化,并增强代码的可维护性。
  • 使用时需要注意不要在可能抛出异常的函数中标记为 noexcept,否则会导致程序终止。

网站公告

今日签到

点亮在社区的每一天
去签到