【问题标题】:Move constructor vs. Move assignment移动构造函数与移动赋值
【发布时间】:2020-03-22 02:15:42
【问题描述】:

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

我有以下代码:

// 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): 错误 C2593: 'operator =' 不明确

linkedlist.h(79):注意:可能是 'LinkedList &LinkedList::operator =(LinkedList &&) noexcept'(指向移动赋值运算符)

linkedlist.h(63): note: or 'LinkedList &LinkedList::operator =(LinkedList) noexcept' (指向复制赋值运算符)

main.cpp(24): 注意:在尝试匹配参数列表时'(LinkedList, LinkedList)'

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

【问题讨论】:

标签: c++ move-assignment-operator


【解决方案1】:

复制赋值运算符将采用const LinkedList&lt;T&gt;&amp; other,而不是LinkedList&lt;T&gt; other

这个

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

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

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

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

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

但由于您已经拥有 swap 和复制+移动构造函数,因此最好使用复制和交换。

PS:由于这些似乎是内联定义(即在类主体中),您可以跳过 &lt;T&gt; 模板参数 - 在 LinkedList 模板类定义中,编写 LinkedList 自动引用“当前实例化"(即LinkedList&lt;T&gt;)。

【讨论】:

  • 现在我已经更新了复制赋值运算符来接收一个 const LinkedList&。现在那不会编译。我正在关注 (stackoverflow.com/questions/3279543) 中的示例
  • @tannic 抱歉,我原本打算删除第二个代码 sn-p 中的主体,因为它们没有意义。实际上,您不能与const LinkedList&amp; 交换(因为它是const) - 您必须先手动构建一个副本(即LinkedList copy(other); swap(*this, copy); return *this;),但最好通过正常方式进行复制和交换来完成。
  • 不知道这个技巧。我在实现移动构造函数时使用operator=(other)
  • @TanveerBadar 如果您的类型已经有 swap,您可以将移动构造函数实现为 default-constructor + swap(*this, other) (但也许有一个更有效的实现 - default-constructing 然后交换一些普通的int 值是浪费精力,你不妨一开始就复制它)。
  • @MaxLanghof:如果我查看上面的链接(复制/交换范式),我会看到这个代码片段,这实际上是我使用的:dumb_array&amp; operator=(dumb_array other) // (1) { swap(*this, other); // (2) return *this; }
猜你喜欢
  • 1970-01-01
  • 2016-05-19
  • 2021-05-31
  • 2015-03-03
  • 2019-09-29
  • 2017-05-15
  • 2013-11-18
  • 1970-01-01
相关资源
最近更新 更多