存在管理资源的类一般还会定义一个swap函数。
定义 swap 函数的原因
在管理资源的类中定义 swap 函数主要有以下几个重要原因:
1. 高效交换资源
通常在进行资源交换时,若采用常规的复制和销毁操作,开销会很大。而使用 swap 函数仅需交换资源的内部指针或者引用,时间复杂度为 O(1),能显著提升效率。
2. 异常安全性
在交换资源时,swap 函数可以保证操作具有强异常安全性。也就是说,若交换过程中出现异常,对象的状态不会发生改变。
3. 与标准库兼容
标准库中的算法(如 std::sort、std::reverse 等)常常会使用 swap 来交换对象。为自定义的资源管理类定义 swap 函数,能让该类更好地与标准库算法协同工作。
示例代码
以下是一个简单的资源管理类 ResourceManager,并定义了 swap 函数:
#include <iostream>
#include <utility>
// 模拟资源类
class Resource {
public:
Resource(int value) : data(value) {
std::cout << "Resource created with value: " << data << std::endl;
}
~Resource() {
std::cout << "Resource destroyed with value: " << data << std::endl;
}
int getData() const {
return data;
}
private:
int data;
};
// 资源管理类
class ResourceManager {
public:
ResourceManager(int value) : resource(new Resource(value)) {}
~ResourceManager() {
delete resource;
}
// 拷贝构造函数
ResourceManager(const ResourceManager& other) : resource(new Resource(other.resource->getData())) {}
// 拷贝赋值运算符
ResourceManager& operator=(ResourceManager other) {
swap(*this, other);
return *this;
}
// 定义 swap 函数
friend void swap(ResourceManager& first, ResourceManager& second) {
using std::swap;
swap(first.resource, second.resource);
}
int getData() const {
return resource->getData();
}
private:
Resource* resource;
};
int main() {
ResourceManager rm1(10);
ResourceManager rm2(20);
std::cout << "Before swap: rm1 data = " << rm1.getData() << ", rm2 data = " << rm2.getData() << std::endl;
swap(rm1, rm2);
std::cout << "After swap: rm1 data = " << rm1.getData() << ", rm2 data = " << rm2.getData() << std::endl;
return 0;
}
代码解释
Resource类:模拟了一个资源,其构造函数和析构函数会输出相应信息,方便观察资源的创建和销毁过程。ResourceManager类:负责管理Resource对象,包含一个指向Resource的指针。- 拷贝构造函数:通过深拷贝的方式创建新的
Resource对象。 - 拷贝赋值运算符:采用了 “拷贝并交换” 技术,借助
swap函数实现资源的交换。 swap函数:交换两个ResourceManager对象的resource指针,避免了资源的复制和销毁操作。
- 拷贝构造函数:通过深拷贝的方式创建新的
在 main 函数中,创建了两个 ResourceManager 对象 rm1 和 rm2,交换它们的资源后,输出交换前后的数据,以此验证 swap 函数的功能。
参考
https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom?rq=1
https://www.bookstack.cn/read/CPlusPlusThings/86395c5695fa6630.md


被折叠的 条评论
为什么被折叠?



