C++ 异常处理`throw`、`try/catch` 与标准异常类(七十二)

1. 抛出异常:throw 表达式

当函数或代码模块发现自身无法继续正常工作、但又无法在本地修复时,就用

throw expr;

来“抛出”一个异常。这里的 expr 可以是:

  • 标准库异常(如 std::runtime_error("…")
  • 自定义的异常类对象
  • 任意可以复制的对象
if (isbn1 != isbn2) {
    // 无法在此处合并记录,抛出运行时错误
    throw std::runtime_error("ISBN must match to combine Sales_data");
}

抛出后,当前函数立即中断,控制流沿调用链向上回溯,寻找匹配的 catch

2. 捕获与处理:try / catch

在可能抛出异常的代码周围,用一个 try 包裹,并紧跟一个或多个 catch 子句

try {
    // 可能会 throw
    auto result = computeBigThing(data);
    std::cout << result << "\n";
}
catch (const std::runtime_error &e) {
    // 针对 runtime_error 的专门处理
    std::cerr << "运行时错误: " << e.what() << "\n";
}
catch (const std::exception &e) {
    // 兜底:处理所有 std::exception 派生的异常
    std::cerr << "其他异常: " << e.what() << "\n";
}
  • 抛出后,第一个匹配抛出类型(或其基类)的 catch 会被执行。
  • 执行完 后,控制流跳到所有 catch 块之后继续,期间栈上被跳过函数的局部对象会正常析构。

3. 标准异常类概览

C++ 标准库在头文件 <stdexcept><exception> 等中定义了一整套常用异常类型:

异常类型语义
std::exception最基类,仅报告“有异常”
逻辑错误<stdexcept>
├─ std::logic_error程序逻辑错误,不是运行时问题(如非法参数)
├─ std::domain_error参数值不在函数定义域内
├─ std::invalid_argument参数格式不合法
├─ std::length_error容器或字符串过长
└─ std::out_of_range下标、迭代器超出有效范围
运行时错误<stdexcept>
├─ std::runtime_error通用运行时错误
├─ std::overflow_error算术运算上溢
├─ std::underflow_error算术运算下溢
└─ std::range_error结果超出允许的数值范围

此外,动态内存分配相关的 <new> 中有 std::bad_alloc;类型转换的 <typeinfo> 中有 std::bad_cast

4. 异常安全最佳实践

  1. 只抛出异常,不在库层直接 exit()
    保持错误处理交给调用者。

  2. 捕获最具体的类型,再捕获基类

    catch(const std::invalid_argument &e) {}
    catch(const std::exception &e) {}  // 兜底
    
  3. 保持异常的基本保证

    • 不抛异常:对外接口尽量不丢失异常。
    • 强烈异常保证:若抛出异常,当前操作无副作用(事务语义)。
  4. 避免使用裸指针管理资源
    结合 RAII(资源获取即初始化)模式:std::unique_ptrstd::vectorstd::string 等,确保栈展开时自动清理。

  5. 不要捕获所有异常并吞掉
    catch(...) 应仅用于日志记录或清理,然后重新抛出,否则程序状态可能不明。

5. 小结

  • throw:抛出运行时检测不到、无法处理的“问题”。
  • try / catch:捕获并专门处理特定类型的错误。
  • 标准异常类:从 std::exception 延伸出丰富的逻辑与运行时错误类型。
  • 异常安全性:通过 RAII、恰当的捕获层次和保证级别,提升程序稳健性。

掌握这一机制后,您就能用简洁优雅的方式,把散落在代码各处的“错误检查”逻辑收拢到少数几个 catch 块中,大大提升可读性和可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello.Reader

请我喝杯咖啡吧😊

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值