移动构造函数与移动赋值

Move constructor vs. Move assignment

作为 问题的扩展,我正在努力使我的移动分配正确。

我有以下代码:

// copy assignment operator
LinkedList<T>& operator= (LinkedList<T> other) noexcept
{
    swap(*this, other);
    return *this;
}

// move assignment operator
LinkedList<T>& operator= (LinkedList<T>&& other) noexcept
{
    swap(*this, other);
    return *this;
}

但是当我尝试使用它时,我的代码无法编译。

首先是一些代码:

LinkedList<int> generateLinkedList()
{
    LinkedList<int> List;   
    List.add(123);
    return List;
}


int main()
{
    LinkedList<int> L;   
    L = generateLinkedList();
      ^ get an error here...

我收到以下错误:

main.cpp(24): error C2593: 'operator =' is ambiguous

linkedlist.h(79): note: could be 'LinkedList &LinkedList::operator =(LinkedList &&) noexcept'(Points to the move assignment operator)

linkedlist.h(63): note: or 'LinkedList &LinkedList::operator =(LinkedList) noexcept' (Points to the copy assignment operator)

main.cpp(24): note: while trying to match the argument list '(LinkedList, LinkedList)'

是我的移动赋值运算符错了,还是我用错了?

复制赋值运算符将采用 const LinkedList<T>& other,而不是 LinkedList<T> other

这个

LinkedList<T>& operator= (LinkedList<T> other) noexcept
{
    swap(*this, other);
    return *this;
}

是如何使用 copy-and-swap 同时实现复制和移动赋值。通过重新使用复制和移动构造函数(other 是复制构造的或移动构造的),您只需将 this 替换为 otherother 在函数结束时死亡,并带走了 this 的旧状态。这个实现完全没问题,但是你不需要对临时对象进行第二次重载(这确实是模棱两可的)。

如果您想为复制赋值和移动赋值提供单独的复制赋值运算符,签名将为

// copy assignment operator
LinkedList<T>& operator=(const LinkedList<T>& other) noexcept
{
  //...
}

// move assignment operator
LinkedList<T>& operator=(LinkedList<T>&& other) noexcept
{
  //...
}

但是因为您已经有了 swap 和复制+移动构造函数,所以最好使用复制和交换。

PS:由于这些似乎是内联定义(即在 class 主体内),您可以跳过 <T> 模板参数 - 在 LinkedList 模板内class定义,写成LinkedList自动指代"current instantiation"(即LinkedList<T>)。