异常安全的核心目标是确保异常发生时程序状态有效:不泄漏资源、不损坏数据、不破坏不变量;C++提供基本、强和不抛异常三类保证,需依托RAII、Copy-and-Swap及noexcept移动/析构实现。

异常安全的核心目标
异常安全不是“不抛异常”,而是确保程序在异常发生时仍保持有效状态:对象不泄漏、数据不损坏、不变量不被破坏。C++中主要关注三类保证:基本异常安全(资源不泄漏,对象处于可析构状态)、强异常安全(操作要么完全成功,要么回滚到调用前状态)、不抛异常安全(noexcept,关键路径如析构函数、移动操作必须满足)。
坚持RAII:资源管理的基石
所有资源(内存、文件、锁、socket等)必须封装在栈对象中,由构造函数获取、析构函数释放。避免裸指针和手动delete/new。
- 用std::unique_ptr替代new/delete,转移所有权自动释放
- 用std::shared_ptr管理共享资源,引用计数保障生命周期
- 互斥锁用std::lock_guard或std::scoped_lock,作用域结束即解锁
- 文件句柄可用std::fstream,RAII自动关闭
编写强异常安全的函数:Copy-and-Swap惯用法
赋值运算符、容器插入等易出错操作,应先完成所有可能抛异常的操作(如内存分配、拷贝),再原子切换状态。
- 实现swap()为noexcept成员函数(通常只交换指针/整数)
- 赋值运算符按“拷贝构造临时对象 → swap → 临时对象析构”流程写
- 例如:
T& operator=(T other) { swap(*this, other); return *this; }(注意参数传值,触发拷贝)
析构函数与移动操作必须noexcept
析构函数若抛异常,可能导致std::terminate;移动构造/赋值若未声明noexcept,容器(如std::vector扩容)将退化为拷贝而非移动。
立即学习“C++免费学习笔记(深入)”;
- 所有析构函数默认隐式noexcept,切勿在其中调用可能抛异常的函数
- 移动操作显式加noexcept:
T(T&&) noexcept { ... } - 自定义swap也应声明为noexcept,供标准库内部调用











