c++++11在异常处理方面引入了noexcept和exception_ptr两个重要特性。① noexcept用于声明函数不抛出异常,语法更简洁且带来性能优化,若函数实际抛出异常则调用std::terminate终止程序;② exception_ptr用于捕获并传递异常,尤其适用于多线程或异步操作中将异常从一个上下文转移到另一个上下文处理。两者用途不同,前者明确接口行为,后者支持异常传递,是互补的工具。

C++11在异常处理方面做了不少改进,其中两个比较重要的特性就是noexcept和“异常指针(exception_ptr)”。这些改动让开发者能更清晰地表达函数是否抛出异常,并提供了更强的异常传递能力。

noexcept:明确声明函数不抛异常
以前我们用throw()来声明一个函数不会抛出任何异常,但在C++11中推荐使用noexcept替代。它不仅语法更简洁,还能带来一定的性能优化。

比如:
立即学习“C++免费学习笔记(深入)”;
void func() noexcept;
这表示func()不会抛出异常。如果它真的抛了,程序会直接调用std::terminate()终止运行。

好处有几个:
- 更高效的代码生成:编译器知道这个函数不会抛异常,就可以省去一些异常处理的开销。
- 接口语义更清晰:调用者可以放心地认为该函数不会中断流程。
- STL容器操作中也广泛使用了
noexcept,用于判断某些操作是否安全。
小贴士:如果你不确定函数是否会抛异常,就不要随便加noexcept。否则一旦抛了异常,后果很严重。
异常指针 exception_ptr:把异常从一个线程传到另一个线程
C++11引入了std::exception_ptr类型,允许你捕获当前的异常并保存下来,之后再在别的地方重新抛出。这对于多线程环境下处理异常非常有用。
举个简单的例子:
#include#include void handle_exception(std::exception_ptr eptr) { try { if (eptr) { std::rethrow_exception(eptr); // 重新抛出异常 } } catch (const std::exception& e) { std::cout << "Caught: " << e.what() << std::endl; } } int main() { std::exception_ptr eptr; try { throw std::runtime_error("Oops!"); } catch (...) { eptr = std::current_exception(); // 捕获当前异常 } handle_exception(eptr); // 在其他上下文中处理 }
这段代码展示了如何在一个地方捕获异常,然后在另一个地方重新抛出。对于异步任务或线程池来说,这种机制非常实用。
几个关键点需要注意:
-
std::current_exception()会复制当前异常对象,所以要确保异常类型是可复制的。 - 使用完
exception_ptr后最好检查是否为nullptr,避免误用。 - 重新抛出时要用
try/catch包裹,否则可能造成程序崩溃。
如何选择使用 noexcept 和 exception_ptr?
这两个特性虽然都属于异常处理体系,但用途不同:
- 如果你想明确告诉别人(以及编译器)某个函数不会抛异常,就用
noexcept。 - 如果你在做跨线程、异步操作,需要传递异常信息,那就考虑使用
exception_ptr。
它们并不是互相替代的关系,而是互补的工具。
基本上就这些。理解这两个特性的应用场景,能让你写出更健壮、更现代的C++代码。










