
在C++中,异常处理机制通过 try、catch 和 throw> 关键字实现,用于在程序运行时检测和响应错误情况。这种机制将错误检测(抛出异常)与错误处理(捕获并恢复)分离,使代码更清晰、健壮。
基本语法结构
一个典型的异常处理流程如下:
try { // 可能抛出异常的代码 throw exception_type("错误信息"); } catch (exception_type& e) { // 处理特定类型的异常 std::cout << "捕获异常:" << e.what() << std::endl; } catch (...) { // 捕获所有其他未被处理的异常 std::cout << "未知异常" << std::endl; }
try 块中包含可能出错的代码。一旦执行 throw 语句,程序会立即跳转到匹配的 catch 块。catch 可以按值、引用或指针接收异常对象,推荐使用引用避免拷贝和对象切片问题。
标准异常类与自定义异常
C++ 标准库定义了一套基于 std::exception 的异常类,位于 <stdexcept> 头文件中,常用包括:
立即学习“C++免费学习笔记(深入)”;
- std::runtime_error:运行时错误
- std::invalid_argument:无效参数
- std::out_of_range:越界访问
- std::logic_error:逻辑错误
你可以继承这些类创建自定义异常:
class MyException : public std::runtime_error { public: MyException(const std::string& msg) : std::runtime_error(msg) {} };
然后在需要时抛出:
throw MyException("发生自定义错误");
异常安全与资源管理
使用异常时,必须确保资源正确释放,如动态内存、文件句柄等。RAII(Resource Acquisition Is Initialization)是C++推荐的做法——利用对象的构造函数获取资源,析构函数自动释放。
例如,用 std::unique_ptr 管理内存,在异常抛出时能自动清理:
std::unique_ptr<int[]> data(new int[100]); // 即使后续 throw,data 析构时也会释放内存
避免在构造函数中抛出未捕获异常前已分配的资源无法回收的问题。
异常规范与 noexcept
C++11 引入了 noexcept 关键字,标明函数不会抛出异常:
void func() noexcept { // 保证不抛异常,若抛出会调用 std::terminate() }
这对性能优化和移动语义很重要。例如,STL 容器在重新分配内存时,若元素的移动构造函数标记为 noexcept,会优先使用移动而非拷贝。
基本上就这些。合理使用 try-catch,结合标准异常和 RAII,能让C++程序更稳定、易维护。注意不要滥用异常处理普通逻辑分支,它适用于“异常”而非“常规”情况。


