用构造函数和 swap 实现 operator=

代码展示

先在参数的位置创建一个新的对象,然后和 *this 交换。

struct MyClass {
    MyClass& operator=(MyClass other) {
        swap(*this, other);
        return *this;
    }

    friend void swap(MyClass &a, MyClass &b) noexcept; {
        using std::swap;
        swap(a.member1, b.member1);
        swap(a.member2, b.member2);
    }

    int member1;
    int member2;
};

这种实现既能够匹配 const MyClass & 的情况,又能匹配 MyClass && 的情况,而且代码行数更短。

注意点 1:必须自定义 swap 函数

使用这种写法必须提供我们自己的 swap 函数,因为 std::swap 对一般类型的实现是使用了构造的,如果不提供我们自己的 swap 函数而去直接调用 std::swap,就会无限递归!std::swap 的相关代码如下:

    void
#endif
    swap(_Tp& __a, _Tp& __b)
    _GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>,
				is_nothrow_move_assignable<_Tp>>::value)
    {
#if __cplusplus < 201103L
      // concept requirements
      __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
#endif
      _Tp __tmp = _GLIBCXX_MOVE(__a);
      __a = _GLIBCXX_MOVE(__b);
      __b = _GLIBCXX_MOVE(__tmp);
    }

注意点 2:实现 swap 函数的时候避免使用 operator=

同时,我们在实现 swap 函数的时候也不应该对本类型对象使用 = 操作符,这也会导致递归调用。swap 函数可以被实现为对本类型的数据成员逐个做 swap

注意点 3:using std::swap

如果直接使用 std::swap 就无法利用上 ADL,可能有些成员是有 swap 友元函数的类型,这个时候用 std::swap 的可能是低效、甚至有错误的。

using std::swap 然后直接使用 swap 就能利用上 ADL。