强异常安全保证要求操作要么完全成功,要么程序状态回滚如初。其实现依赖于事务性语义,典型方法是“拷贝与交换”:先在临时对象上完成可能抛异常的操作,再通过不抛异常的交换操作提交结果,确保异常发生时状态不变,适用于需高可靠性的关键逻辑。

在c++中,强异常安全保证(Strong Exception Safety Guarantee)指的是:如果一个操作抛出异常,程序的状态会回滚到该操作开始之前的状态,就像这个操作从未发生过一样。这种保证也常被称为“事务性语义”或“提交或回滚(Commit-or-Rollback)”行为。
什么是强异常安全保证
异常安全有三个常见级别:
- 基本保证:异常抛出后,对象仍处于有效状态,但结果不确定。
- 强保证:操作要么完全成功,要么程序状态恢复如初。
- 无抛出保证:操作不会抛出异常(通常用于析构函数和swap等)。
强异常安全属于中间偏高的安全级别,它要求在异常发生时,对外可见的状态不被部分修改——即具备原子性。
事务性语义与Commit-or-Rollback
强异常安全本质上模拟了数据库中的事务机制:操作要么全部生效(commit),要么完全撤销(rollback)。在C++中实现这一语义的关键是:
立即学习“C++免费学习笔记(深入)”;
- 将可能抛出异常的操作放在改变对象状态之前完成。
- 使用临时对象或资源进行预计算或预备变更。
- 通过不抛出异常的操作(如指针交换、swap())来提交变更。
典型做法是“拷贝与交换”(copy-and-swap)惯用法。例如:
class MyClass {
private:
std::vector
public:
void setData(const std::vector
// 先在局部副本上操作,可能抛异常
MyClass temp = *this;
temp.data = new_data;
// 提交:交换数据,swap通常不抛异常
data.swap(temp.data);
}
};
在这个例子中,赋值操作的所有潜在异常都在创建临时对象时发生。一旦进入swap阶段,就不会改变程序状态,从而实现了强异常安全。
如何设计支持强保证的接口
要提供强异常安全,需注意以下几点:
- 避免在未完成准备时修改原始对象。
- 优先使用已知不抛异常的操作作为最后一步。
- 利用RAII管理资源,防止泄漏。
- 对复杂操作分阶段处理:准备 → 验证 → 提交。
比如容器的push_back如果可能导致重新分配,在没有备用内存时会抛出异常,此时必须确保原有元素不受影响——标准库容器大多为此做了精心设计。
基本上就这些。强异常安全不是免费的(可能带来性能开销),但在关键逻辑中非常必要。通过事务式设计,可以让代码更健壮、可预测。