代码示例:

代码语言:cpp

代码运行次数:0

运行

AI代码解释

#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;
}

输出:

代码语言:txt

AI代码解释

safeFunction called
Exception caught: An error occurred

如果将unsafeFunction标记为noexcept

代码语言:cpp

代码运行次数:0

运行

AI代码解释

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

输出:

代码语言:txt

AI代码解释

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

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

2. 作为运算符

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

特性:

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

代码示例:

代码语言:cpp

代码运行次数:0

运行

AI代码解释

#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;
}

输出:

代码语言:txt

AI代码解释

safeFunction noexcept: 1
unsafeFunction noexcept: 0
3. 性能优化

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

代码示例:

代码语言:cpp

代码运行次数:0

运行

AI代码解释

#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;
}

输出:

代码语言:txt

AI代码解释

safeFunction took 100 ms
unsafeFunction took 100 ms

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

4. 异常安全性

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

代码示例:

代码语言:cpp

代码运行次数:0

运行

AI代码解释

#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也可以帮助你提高代码的异常安全性,特别是在使用移动语义时。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐