C++中noexcept的具体特性及其代码示例

举报
码事漫谈 发表于 2025/06/30 14:17:57 2025/06/30
【摘要】 1. 作为异常说明符 2. 作为运算符 3. 性能优化 4. 异常安全性 总结 1. 作为异常说明符noexcept可以放在函数声明或定义的后面,表示该函数不会抛出任何异常。如果函数在运行时抛出异常,程序会立即终止,并调用std::terminate()函数。特性:编译时检查:编译器会检查函数是否可能抛出异常。如果函数内部调用了可能抛出异常的代码,编译器会报错。运行时终止:如果标记为noe...

1. 作为异常说明符

noexcept可以放在函数声明或定义的后面,表示该函数不会抛出任何异常。如果函数在运行时抛出异常,程序会立即终止,并调用std::terminate()函数。

特性:

  • 编译时检查:编译器会检查函数是否可能抛出异常。如果函数内部调用了可能抛出异常的代码,编译器会报错。
  • 运行时终止:如果标记为noexcept的函数在运行时抛出异常,程序会立即终止。

代码示例:

#include <iostream>
#include <stdexcept>

void safeFunction() noexcept {
    // 这个函数不会抛出异常
    std::cout << "safeFunction called" << std::endl;
}

void unsafeFunction() {
    // 这个函数可能会抛出异常
    throw std::runtime_error("An error occurred");
}

int main() {
    try {
        safeFunction();
        unsafeFunction(); // 这里会抛出异常
    } catch (const std::exception& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }
    return 0;
}

输出:

safeFunction called
Exception caught: An error occurred

如果将unsafeFunction标记为noexcept

void unsafeFunction() noexcept {
    // 这个函数可能会抛出异常
    throw std::runtime_error("An error occurred");
}

输出:

safeFunction called
terminate called after throwing an instance of 'std::runtime_error'
  what():  An error occurred

程序会立即终止,并调用std::terminate()

2. 作为运算符

noexcept(expression)用于检查表达式是否可能抛出异常。如果表达式不会抛出异常,则返回true;否则返回false

特性:

  • 编译时检查:编译器会检查表达式是否可能抛出异常。
  • 返回值:返回一个布尔值,表示表达式是否安全。

代码示例:

#include <iostream>
#include <stdexcept>

void safeFunction() noexcept {
    std::cout << "safeFunction called" << std::endl;
}

void unsafeFunction() {
    throw std::runtime_error("An error occurred");
}

int main() {
    std::cout << "safeFunction noexcept: " << noexcept(safeFunction()) << std::endl;
    std::cout << "unsafeFunction noexcept: " << noexcept(unsafeFunction()) << std::endl;
    return 0;
}

输出:

safeFunction noexcept: 1
unsafeFunction noexcept: 0

3. 性能优化

标记为noexcept的函数,编译器可以进行一些优化,例如删除异常处理代码、进行函数内联等,从而提高程序的性能。

代码示例:

#include <iostream>
#include <chrono>

void safeFunction() noexcept {
    // 这个函数不会抛出异常
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void unsafeFunction() {
    // 这个函数可能会抛出异常
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

int main() {
    auto start = std::chrono::high_resolution_clock::now();
    safeFunction();
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "safeFunction took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;

    start = std::chrono::high_resolution_clock::now();
    unsafeFunction();
    end = std::chrono::high_resolution_clock::now();
    std::cout << "unsafeFunction took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << " ms" << std::endl;

    return 0;
}

输出:

safeFunction took 100 ms
unsafeFunction took 100 ms

虽然在这个简单的例子中性能差异不明显,但在复杂的程序中,noexcept可以显著提高性能。

4. 异常安全性

使用noexcept可以提高代码的异常安全性。标记为noexcept的函数不会抛出异常,因此调用这些函数的代码可以更加自信地使用不带RAII(资源获取即初始化)的代码。

代码示例:

#include <iostream>
#include <vector>

class MyClass {
public:
    MyClass(int value) : value_(value) {}
    int value() const { return value_; }

    // 移动构造函数
    MyClass(MyClass&& other) noexcept : value_(other.value_) {
        other.value_ = 0;
    }

    // 移动赋值运算符
    MyClass& operator=(MyClass&& other) noexcept {
        if (this != &other) {
            value_ = other.value_;
            other.value_ = 0;
        }
        return *this;
    }

private:
    int value_;
};

void testMove() noexcept {
    std::vector<MyClass> vec;
    vec.reserve(10);

    for (int i = 0; i < 10; ++i) {
        vec.emplace_back(i);
    }

    std::vector<MyClass> vec2 = std::move(vec);
}

int main() {
    testMove();
    return 0;
}

在这个例子中,MyClass的移动构造函数和移动赋值运算符都被标记为noexcept,这使得std::vector在进行内存重新分配等操作时可以安全地使用移动语义。

总结

noexcept是一个非常有用的特性,它可以帮助你编写更安全、更高效的代码。通过标记函数为noexcept,你可以告诉编译器这些函数不会抛出异常,从而让编译器进行优化。同时,noexcept也可以帮助你提高代码的异常安全性,特别是在使用移动语义时。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。