异常安全确保C++程序在异常下保持有效状态,包含三个级别:基本保证(状态有效但可能改变)、强保证(操作要么成功要么回滚)和无异常保证(绝不抛出异常),通过RAII、copy-and-swap等技术实现。

在C++中,异常安全(Exception Safety)指的是当程序在执行过程中抛出异常时,程序仍能保持良好的状态——不会发生资源泄漏、数据损坏或违反类的不变式。编写具有异常安全性的代码是构建可靠、可维护系统的关键部分。为此,C++社区提出了三种主要的异常安全保证级别:基本保证、强保证和无异常保证。
基本异常安全保证(Basic Exception Safety)
也称为“提交-回滚”语义。如果一个操作抛出异常,程序的状态仍然是有效的,即所有对象保持其不变式成立,没有资源泄漏,但具体状态可能与调用前不同。
- 对象不会进入无效状态
- 已分配的资源会被正确释放(如内存、文件句柄等)
- 不保证操作完全回退到原始状态
例如,在向容器插入元素时发生异常,原有元素仍然有效,新元素可能未插入,但容器本身不会崩溃或处于损坏状态。
强异常安全保证(Strong Exception Safety)
又称“事务性语义”。操作要么完全成功,要么像没发生过一样——程序状态回滚到调用前的样子。
立即学习“C++免费学习笔记(深入)”;
- 若异常抛出,程序状态与调用前一致
- 常通过“拷贝-交换”(copy-and-swap)惯用法实现
- 适用于对一致性要求高的场景,比如修改关键数据结构
典型做法是先在临时对象上完成修改,确认无异常后再原子地交换原对象内容。这样即使中途失败,原对象不受影响。
无异常保证(Nothrow Guarantee)
函数承诺不会抛出异常。这是最强的安全级别,通常用于析构函数、移动赋值(如果类型支持)以及某些标准库接口。
- 函数内部处理所有潜在错误,不向上传播异常
- 常标记为 noexcept
- 对性能敏感或必须保证继续执行的代码至关重要
比如 std::swap 在适当实现下可以是 noexcept 的,这使得它能在异常环境中安全使用。
为了达到这些保证,开发者应:
- 使用 RAII 管理资源(智能指针、锁包装器等)
- 避免裸 new/delete,优先使用容器和标准库组件
- 在修改多个对象时,注意操作顺序和中间状态的可控性
- 尽量将可能失败的操作前置,成功后再修改原始数据
基本上就这些。异常安全不是附加功能,而是设计时就要考虑的编码原则。理解并应用这三类保证,能让C++代码在面对意外时依然稳健。







