背景
STL 中提供了 swap 算法,用于交换两个对象的值。对于资源管理类,我们可以提供自定义的高效 swap 以仅交换指针。
通常包含资源(指针)的类需要提供自定义的拷贝及移动相关操作函数。
资源管理类
①.概述
通常包含资源(指针)的类需要提供自定义的构造及析构函数。
②.类定义
class demoClass
{
public:
demoClass(const string& s = string()) :str(new string(s)) { }
demoClass(const demoClass& d):str(new string(*d.str)){}
~demoClass(){ delete str; }
...
private:
string* str;//指针
};
拷贝赋值运算符的实现
①.概述:
拷贝赋值运算符的实现一般包括以下步骤:考虑自我赋值,拷贝新的资源,若拷贝成功则释放旧资源、赋值新数据。
②.代码示例:
demoClass& operator=(const demoClass& d)
{
auto newStr = new string(*d.str);//拷贝新资源
delete str;//释放旧资源
str = newStr;//赋新值
return *this;
}
③.存在问题
这里的拷贝赋值运算符可以正常工作,满足自我赋值、强异常安全保证,但主要问题是存在代码冗余,需要把构造及析构函数中的代码复制一遍。
移动赋值运算符的实现
①.概述:
移动赋值运算符的实现一般包括以下步骤:考虑自我赋值,拷贝新的资源,若拷贝成功则释放旧资源、赋值新数据。
②.代码示例
demoClass& operator=( demoClass&& d) noexcept
{
if (this != &d)
{
delete str;//释放旧资源
str = d.str;//接管新资源
d.str = nullptr;//被移动的资源置于可析构状态
}
return *this;
}
copy and swap
①.自定义 swap
void swap(demoClass& d1, demoClass& d2) noexcept
{
using std::swap;
swap(d1.str, d2.str);//交换指针
}
②.统一赋值函数
通过传值操作传递右侧对象,然后进行交换操作实现对象的赋值。若实现了拷贝构造函数和移动构造函数,无论是左值还是右值,均可通过该函数进行赋值。
demoClass& operator=( demoClass d)
{
swap(*this, d);
return *this;
}