C++ 中的异常处理机制提供了一种优雅、结构化的方式来处理程序运行中的错误或特殊情况。它通过 try-catch-throw
三个关键字实现,类似于其他现代语言如 Java、Python,但又有其 C++ 特有的细节。
下面是详细的讲解:
✅ 一、C++ 异常处理的基本结构
try { // 可能抛出异常的代码 } catch (类型1 异常对象1) { // 处理类型1的异常 } catch (类型2 异常对象2) { // 处理类型2的异常 } catch (...) { // 处理所有其他未知类型的异常(兜底) }
示例:
#include <iostream> using namespace std; int divide(int a, int b) { if (b == 0) throw runtime_error("Divide by zero"); return a / b; } int main() { try { int result = divide(10, 0); cout << "Result: " << result << endl; } catch (const runtime_error& e) { cout << "Caught exception: " << e.what() << endl; } catch (...) { cout << "Caught unknown exception" << endl; } }
✅ 二、throw 抛出异常
throw
表达式用于抛出一个异常对象。可以抛出任意类型(整型、字符串、类对象等),但推荐抛出类对象(如
std::exception
或其子类)以提供更丰富的上下文信息。
示例:
throw 42; // 抛出 int 类型 throw "Error occurred"; // 抛出 const char* throw std::runtime_error("Oops"); // 推荐做法
✅ 三、标准异常类(来自 <stdexcept>
)
C++ 标准库定义了一套异常类,继承自 std::exception
:
异常类型 | 描述 |
---|---|
std::exception | 所有标准异常的基类 |
std::runtime_error | 运行时错误 |
std::logic_error | 逻辑错误(程序员错误) |
std::out_of_range | 越界访问 |
std::invalid_argument | 非法参数 |
std::bad_alloc | 内存分配失败(如 new 失败) |
std::bad_cast | 错误的类型转换 |
捕获标准异常示例:
try { throw std::out_of_range("Index too large"); } catch (const std::exception& e) { cout << "Error: " << e.what() << endl; }
✅ 四、catch(…) 捕获所有异常
catch (...) { // 捕获任何类型的异常(最后一道防线) }
✅ 五、自定义异常类
可以自定义继承自 std::exception
的异常类:
class MyException : public std::exception { public: const char* what() const noexcept override { return "My custom exception"; } };
✅ 六、注意事项与最佳实践
✅ 推荐
抛出并捕获类对象,尤其是
std::exception
子类。使用
const&
捕获异常对象,避免拷贝。只在真正需要处理错误的地方使用异常。
❌ 不推荐
在性能敏感的核心循环中使用异常(异常处理比条件分支要慢)。
抛出裸指针或字符串字面量。
忽略异常(空
catch(...)
)。
✅ 七、异常安全性等级(Advanced)
当设计库/类时,常讨论异常安全保证等级:
等级 | 含义 |
---|---|
不抛异常(nothrow) | 永远不会抛出异常 |
基本保证 | 异常发生时,对象仍保持有效状态 |
强保证 | 操作要么完全成功,要么无任何副作用 |
提升保证(事务级) | 多个操作要么全部成功,要么全部回滚 |
✅ 八、现代 C++ 特性(C++11+)
noexcept
关键字:标明函数不会抛出异常,有助于优化void myFunc() noexcept;
std::current_exception()
/std::rethrow_exception()
:用于异常转发和捕获链(用于多线程)
系统当前共有 440 篇文章