文章目录

C++ 异常处理:try-catch 与 throw

发布于 2026-04-07 09:19:13 · 浏览 15 次 · 评论 0 条

C++ 异常处理:try-catch 与 throw

传统错误处理依赖函数返回值与全局状态码判断,代码容易陷入深层嵌套且难以统一接管。异常处理机制将正常业务逻辑与错误恢复代码物理隔离,让程序在遇到不可恢复状态时自动中断当前执行流,精准跳转至预设处理分支。


  1. 引入 必要标准库:在源文件头部添加 #include <exception>#include <string>。前者提供基础异常类定义,后者支持错误字符串的安全传递与解析。
  2. 包裹 风险执行区:使用 try 关键字后接花括号 {},将可能引发运行时中断的逻辑(如文件读写、网络请求、动态数组访问)完整移入块内。编译器会在此区域隐式植入状态检查点。
  3. 植入 条件判断语句:在 try 块内部编写 校验逻辑。当业务数据或环境状态不满足安全要求时,立即触发错误分支,阻止破坏性操作继续向底层蔓延。
  4. 抛出 错误载体:调用 throw 关键字后接一个具体数据对象。该对象作为错误信号被压入临时存储区。传递 基础类型(如 int 状态码)或标准库异常对象(如 std::runtime_error)。
  5. 部署 类型拦截器:在 try 块闭合花括号正下方排列 catch 块。圆括号 () 内声明参数类型与变量名。当 throw 被激活,运行时环境会遍历 下方所有 catch,寻找类型完全匹配或可隐式转换的声明。
  6. 执行 恢复逻辑:在匹配的 catch 大括号内编写 补偿操作。记录 错误上下文日志,释放 临时占用资源,返回 降级后的安全默认值,或重新抛出 给上层调用栈处理。

完整编码结构示例如下:

#include <iostream>
#include <stdexcept>

int calculate_division(int dividend, int divisor) {
    if (divisor == 0) {
        throw std::invalid_argument("除数不允许为零");
    }
    return dividend / divisor;
}

int main() {
    int result = 0;

    try {
        result = calculate_division(10, 0);
        std::cout << "计算结果:" << result << std::endl;
    }
    catch (const std::invalid_argument& err) {
        std::cout << "拦截参数错误:" << err.what() << std::endl;
        result = 0;
    }
    catch (...) {
        std::cout << "拦截未知运行时故障" << std::endl;
        result = -1;
    }

    return 0;
}
捕获声明方式 匹配规则 适用场景 性能与内存开销
catch (std::exception e) 按值拷贝匹配 仅读取错误信息且无需修改内部状态 产生对象副本,开销略高
catch (const std::exception& e) 引用绑定匹配 标准业务错误接管(推荐写法) 零拷贝,性能最优
catch (std::exception* e) 指针地址匹配 堆分配异常的精细管理 需手动调用 delete 防泄漏
catch (...) 通配符匹配 兜底拦截未预见错误 开销极低,仅获取控制权

  1. 剥离 析构函数中的异常代码:C++ 对象生命周期结束时会调用析构函数。若析构过程中再次抛出 异常,且原调用栈已存在未处理异常,运行时将直接调用 std::terminate 强制终止进程。将资源释放失败的情况转为 内部日志写入或状态标记,绝不向外抛出信号。
  2. 替换 动态内存为智能指针:异常触发瞬间,系统会执行栈展开操作,自动调用当前栈帧所有局部对象的析构函数。若使用裸指针管理堆内存,指针变量销毁但指向的内存不会被释放。将 new 分配替换std::make_uniquestd::make_shared,利用智能指针的析构契约确保内存绝对安全回收。
  3. 统一 自定义错误继承链:所有业务专属异常类必须公开继承 std::exception重写 what() 虚函数并返回固定错误描述字符串。外部调用方只需捕获 std::exception 基类引用,即可通过多态机制直接读取 what() 内容,避免编写冗长的类型分支判断。
  4. 收敛 异常穿透作用域:跨动态链接库(DLL/so)边界抛出异常可能导致二进制接口不兼容与内存分配器错乱。在模块对外导出接口处增加 转换层,将内部异常捕获 后转为标准错误码或 HRESULT 结构体返回,阻断异常跨越编译边界。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文