copy-and-swap: 拷贝赋值函数的简单实现

目录

copy-and-swap: 拷贝赋值函数的简单实现#

首先明确一点: 如果没有必要定义拷贝构造函数/拷贝赋值函数/析构函数, 就不要定义, 让编译器为你声明甚至定义.

如果有定义的需求, 且拷贝仅仅是拷贝, 不是因为题目而有输出之类的特殊要求, 则可以先定义拷贝构造函数、析构函数, 然后利用它们定义拷贝赋值函数, 这称为 copy-and-swap 惯用法.

拷贝赋值函数#
1Widget& operator=(Widget const& other) {
2  Widget temp(other);  // 拷贝 other 到 temp
3  swap(*this, temp);   // 交换 temp 和 *this 的内容; 该函数怎么来的见下文
4  return *this;
5}  // temp 的析构函数将会对交换来的 *this 内容完成必要的清理
swap 函数#
1// 如果是 C++11 及以后, 加上 noexcept 表示不会抛出异常 ↓
2friend void swap(Widget& lhs, Widget& rhs) noexcept {
3  /* 交换 lhs 和 rhs 的所有成员 */
4}

提示

注意到, 这样一来没有必要判断自赋值情况 widget = widget——自赋值单纯就是得到一份自己的拷贝, 然后与该拷贝发生交换, 最终得到内容仍然是自己.

示例#

[在线代码 fjcjKMGce]

 1#include <utility>  // for std::swap
 2
 3class Widget {
 4 public:
 5  Widget(Widget const& other);
 6
 7  Widget& operator=(Widget const& other) {
 8    Widget temp(other);  // 拷贝 other 到 temp
 9    swap(*this, temp);   // 交换 temp 和 *this 的内容
10    return *this;
11  }  // temp 的析构函数将会对交换来的 *this 内容完成必要的清理
12
13  ~Widget();
14
15  // 如果是 C++11 及以后, 加上 noexcept 表示不会抛出异常 ↓
16  friend void swap(Widget& lhs, Widget& rhs) /*noexcept*/ {
17    using std::swap;  // 先 using std::swap, 再使用不加限定的 swap
18    swap(lhs.array_, rhs.array_);
19    swap(lhs.size_, rhs.size_);
20  }
21
22 private:
23  int* array_;
24  int size_;
25};