C++ 异常处理需用成对的 try-catch 结构:try 块包裹可能抛异常的代码,后接一个或多个 catch 块捕获对应类型异常,如 catch(const std::runtime_error& e)处理运行时错误。

C++ 用 try-catch 块配合 throw 表达式实现异常处理,核心是把错误检测(throw)和错误响应(catch)分离,让程序在出错时能安全跳转到处理逻辑,而不是崩溃或未定义行为。
try-catch 基本结构怎么写?
必须成对使用:try 块包裹可能抛异常的代码,后面紧跟一个或多个 catch 块来捕获对应类型的异常:
try {// 可能抛异常的操作,比如除零、内存分配失败、自定义检查 if (x == 0) throw std::runtime_error(" 除数不能为零 "); int* p = new int[1000000]; // 可能抛 std::bad_alloc } catch (const std::runtime_error& e) {std::cerr << " 运行时错误:" << e.what() << 'n'; } catch (const std::bad_alloc& e) {std::cerr << " 内存分配失败:" << e.what() << 'n'; } catch (……) {std::cerr << " 捕获了未知类型的异常 n ";}
- 每个
catch按类型匹配,从上到下顺序尝试,只执行第一个匹配的块 - 推荐按引用捕获(
const T&),避免对象切片和不必要的拷贝 -
catch(……)是兜底项,只能放在最后,捕获所有类型(但无法获取异常值)
throw 抛出什么才算“合法”异常?
C++ 允许 throw 任意类型(int、string、自定义类等),但最佳实践是抛出继承自 std::exception 的对象:
- 标准库提供常用异常类:如
std::logic_error(逻辑错误)、std::runtime_error(运行时错误)、std::invalid_argument、std::out_of_range等 - 自定义异常只需继承
std::exception或其子类,并重载what()成员函数返回 C 风格字符串 - 避免抛出裸指针、临时对象地址或局部变量引用——它们在栈展开时已销毁
异常安全的关键细节有哪些?
异常发生时,C++ 会自动执行 栈展开(stack unwinding):依次调用当前作用域内已构造对象的析构函数。这是资源管理(如 RAII)起效的基础:
立即学习“C++ 免费学习笔记(深入)”;
- 确保关键资源(文件句柄、锁、动态内存)由具有析构函数的类管理(例如
std::fstream、std::lock_guard、std::unique_ptr) - 不要在析构函数里抛异常(C++11 起默认为
noexcept,否则直接调用std::terminate) - 函数可声明异常规范(如
void f() noexcept;),明确表示不抛异常,违反则终止程序
常见误区和实用建议
新手容易忽略这些点:
- 没写
catch且异常未被任何 handler 捕获 → 程序调用std::terminate终止 - 在
catch块里忘记重新抛出(throw;)就结束,导致异常“消失”,上层无法感知 - 过度使用异常替代正常流程控制(比如用异常实现循环退出)——性能差且语义不清
- 跨 DLL/so 边界抛异常可能失败,建议用错误码或统一异常接口封装
基本上就这些。异常机制本身不复杂,但用好需要理解栈展开、RAII 和类型匹配的配合。写代码时优先考虑“哪里可能出错”,再决定 throw 还是返回错误码,保持风格一致。






























