强异常安全的swap通过拷贝和交换实现,先复制可能抛出异常,swap本身用noexcept交换指针和大小,确保赋值要么成功要么无影响。

在C++中,实现一个强异常安全的
swap函数是确保资源管理类在异常发生时仍能保持对象状态一致的关键。强异常安全保证:如果操作抛出异常,程序状态回滚到操作前的状态,即“要么成功,要么无影响”。
swap 的基本作用
swap函数用于交换两个对象的内部资源。标准库中很多容器和算法会频繁调用
swap,因此它的异常安全性至关重要。理想情况下,
swap应是无异常(nothrow)的,以支持更高效的移动语义和异常安全策略。
使用拷贝和交换惯用法(Copy-and-Swap)
实现强异常安全
swap的常用方法是“拷贝和交换”惯用法。核心思想是:先创建副本(可能抛出异常),再通过无异常的
swap提交更改。 示例:一个资源管理类的实现
假设我们有一个管理动态内存的类:
class MyResource {
private:
int* data;
size_t size;
public:
explicit MyResource(size_t s = 0) : data(s ? new int[s] : nullptr), size(s) {}
~MyResource() { delete[] data; }
MyResource(const MyResource& other)
: data(other.size ? new int[other.size] : nullptr), size(other.size)
{
std::copy(other.data, other.data + size, data);
}
MyResource& operator=(MyResource other) // 注意:按值传参,自动调用拷贝构造
{
swap(*this, other); // 强异常安全:swap 不抛出异常
return *this;
}
friend void swap(MyResource& a, MyResource& b) noexcept
{
using std::swap;
swap(a.data, b.data);
swap(a.size, b.size);
}};
立即学习“C++免费学习笔记(深入)”;
冰兔(Btoo)网店系统
系统简介:冰兔BToo网店系统采用高端技术架构,具备超强负载能力,极速数据处理能力、高效灵活、安全稳定;模板设计制作简单、灵活、多元;系统功能十分全面,商品、会员、订单管理功能异常丰富。秒杀、团购、优惠、现金、卡券、打折等促销模式十分全面;更为人性化的商品订单管理,融合了多种控制和独特地管理机制;两大模块无限级别的会员管理系统结合积分机制、实现有效的推广获得更多的盈利!本次更新说明:1. 增加了新
下载
为什么这个 swap 是强异常安全的?
- 赋值操作中,参数
other
是通过值传递的,这意味着拷贝构造可能抛出异常,但发生在赋值函数体之前。如果拷贝失败,原对象不会被修改。 swap
函数标记为noexcept
,且仅交换指针和整数,这些基本操作不会抛出异常。- 交换完成后,旧资源随
other
的析构被自动释放。
这种设计确保了赋值操作满足强异常安全:要么赋值成功,要么原对象保持不变。
关键注意事项
要确保
swap真正强异常安全,需注意以下几点:
-
自定义 swap 必须 noexcept:交换基本类型(指针、int等)不会抛出,应显式标记
noexcept
。 -
避免在 swap 中分配资源:swap 体内不应有
new
、dynamic_cast
等可能抛出的操作。 -
特化 std::swap(可选):若希望标准算法使用高效 swap,可特化
std::swap
,但通常依赖ADL(参数依赖查找)找到友元swap
即可。
基本上就这些。只要 swap 本身不抛出异常,并在拷贝构造可能失败时推迟状态变更,就能实现强异常安全。这种模式在 RAII 类中非常普遍,是 C++ 异常安全编程的基石之一。








