必须用 const 引用捕获 std::exception:catch (const std::exception& e),避免切片、二次异常和临时对象绑定失败;具体类型如 std::out_of_range 需放在通用捕获前;需包含对应头文件,且异常对象生命周期由系统管理。

捕获 std::exception 及其派生类必须用 const 引用
直接写 catch (std::exception e) 看似可行,但会触发对象切片和潜在二次异常:如果 e 是 std::runtime_error,值传递会丢掉派生类信息;更糟的是,拷贝构造过程若抛异常(比如内存不足),程序立刻调用 std::terminate()。所以必须写成:
-
catch (const std::exception& e)—— 安全、高效、保留完整类型信息 - 不要漏掉
const:std::exception对象通常不可修改,且非const引用无法绑定临时对象(throw 创建的就是临时异常对象) - 这个 catch 能捕获所有标准库异常:
std::runtime_error、std::logic_error、std::out_of_range、std::bad_alloc等
具体异常类型要放在通用 catch 前面
标准库异常是继承体系,std::out_of_range 是 std::exception 的子类。如果把 catch (const std::exception& e) 写在最前,后面再跟 catch (const std::out_of_range& e),后者永远没机会执行。
- 按从具体到宽泛顺序排列:先
catch (const std::out_of_range&),再catch (const std::runtime_error&),最后catch (const std::exception&) - 别依赖
catch ()(省略号)来兜底——它不提供任何异常对象,连e.what()都不能调,仅适合日志记录后立即终止 - 实际项目中,
catch (const std::exception&)已足够覆盖绝大多数标准库异常,无需额外加catch ()
std::bad_alloc 捕获要特别注意位置和时机
std::bad_alloc 是唯一一种可能在你完全没调用 throw 的地方自动抛出的异常(比如 new 失败)。但它不是“静默失败”,而是明确抛异常——前提是没重载全局 operator new 并设为 noexcept。
- 它属于
std::exception体系,所以catch (const std::exception&)能捕获 - 但如果你需要区分内存分配失败和其他错误,应单独写
catch (const std::bad_alloc&),并放在std::exception之前 - 注意:C++11 起,
new默认抛std::bad_alloc;若用new (std::nothrow),则返回nullptr而不抛异常,此时根本进不了 catch 块
别忘了包含头文件和命名空间
很多初学者写了 catch (const std::runtime_error&) 却编译失败,原因就在这两处遗漏:
立即学习“C++免费学习笔记(深入)”;
- 必须
#include <stdexcept>才能使用std::runtime_error、std::logic_error等;std::bad_alloc在<new>中;std::out_of_range也在<stdexcept> -
std::exception定义在<exception>,但多数情况只需包含<stdexcept>(它已间接包含<exception>) - 不要在全局作用域用
using namespace std;—— 尤其在头文件里,容易污染;显式写std::更安全、可读性更强
catch 块里拿到的引用,指向的是运行时系统管理的一块稳定内存,不是即将销毁的局部变量。这点决定了为什么必须用引用——值传递不仅低效,而且语义危险。


















