c++如何处理程序异常 try-catch语句的使用方法【代码健壮性】

C++中try-catch通过try块包裹可能出错代码,遇throw或标准库异常时跳转至匹配catch处理,避免程序崩溃。

在 C++ 中,用 try-catch 捕获并处理异常,是提升代码健壮性的核心手段。它让程序在遇到意外(比如除零、内存不足、文件打不开)时,不直接崩溃,而是有控制地恢复或给出友好提示。

基本结构:try 块包裹可能出错的代码

try 后面紧跟一对花括号,里面放那些可能抛出异常的操作。一旦其中某行代码用 throw 主动抛出异常,或者调用了会抛异常的标准库函数(如 std::stoi 遇到非法字符串),程序就会立即跳出 try 块,寻找匹配的 catch

示例:

try {
    int x = std::stoi("abc"); // 抛出 std::invalid_argument
    std::cout << "x = " << x << "\n";
} catch (const std::invalid_argument& e) {
    std::cerr << "输入格式错误:" << e.what() << "\n";
}

catch 块要精准匹配异常类型

不要只写 catch(...)(捕获所有),它像“兜底”一样容易掩盖问题。优先按具体异常类型逐个捕获,顺序从派生类到基类(比如先 std::out_of_range,再 std::exception),否则子类异常会被父类提前截获。

  • 捕获引用(const std::exception& e)避免对象切片和不必要的拷贝
  • 标准异常都继承自 std::exception,它的 what() 方法返回错误描述
  • 自定义异常类也应继承 std::exception 或其子类,保持统一接口

throw 不只是抛内置异常,也能抛自定义信息

除了抛标准异常对象,你也可以用 throw 抛基本类型(如 throw 42;throw "file not found";),但不推荐——缺乏类型安全和可扩展性。更规范的做法是定义自己的异常类:

struct FileOpenError : public std::runtime_error {
    explicit FileOpenError(const std::string& path)
        : std::runtime_error("无法打开文件: " + path) {}
};

// 使用
if (!file.is_open()) {
    throw FileOpenError("config.txt");
}

资源管理别忘 RAII,try-catch 不替代析构

try-catch 解决的是“出错怎么办”,但不是“怎么确保资源释放”。C++ 中应依赖 RAII(如 std::fstreamstd::unique_ptr),让对象生命周期自动管理资源。即使发生异常,栈展开(stack unwinding)也会调用局部对象的析构函数。

  • 不要在 catch 里手动 delete 原始指针——改用智能指针
  • 若必须在异常路径中清理,把清理逻辑封装进析构函数,而非塞进 catch
  • 避免在析构函数里抛异常(会导致程序终止),必要时用 noexcept 明确标记