【问题标题】:using swap to implement move assignment使用swap实现移动赋值
【发布时间】:2015-11-20 23:09:45
【问题描述】:

我发生了一些我认为完全合理的事情,但我希望人们对此发表意见,以防我完全错过了什么。所以首先,我对T& operator=(T&& rhs) 的理解是,我们不在乎当我们完成时rhs 的内容是什么,只是内容已经移入this 并且@ 987654326@ 可以安全销毁。

话虽如此,复制赋值运算符的常见异常安全实现,假设交换成本低廉,如下所示:

T& operator=(const T& rhs) {
    if(this != &rhs) {
        T(rhs).swap(*this);
    }
    return *this;
}

因此,实现移动赋值运算符的一种自然方式如下:

T& operator=(T&& rhs) {
    if(this != &rhs) {
        T(std::move(rhs)).swap(*this);
    }
    return *this;
}

但后来我突然想到,rhs 不必为空!那么,为什么不直接做一个简单的swap

T& operator=(T&& rhs) {
    rhs.swap(*this); // is this good enough?
    return *this;
}

认为这满足了移动分配操作员需要做的事情......但就像我说的,这只是发生在我身上,所以我认为我可能遗漏了一些东西.

我能想到的唯一“缺点”是this 拥有的东西与使用移动构造/交换的版本相比,使用普通交换可能会更长寿。

想法?

【问题讨论】:

  • 我更喜欢这个答案末尾的移动分配:stackoverflow.com/a/3279550/4342498
  • 请注意,您可以使用T& operator=(T rhs) { rhs.swap(*this); return *this; }同时实现两个交换
  • 我们不关心完成后 rhs 的内容是什么 是的,我们这样做:它必须处于析构函数的有效状态。例如,当指针传递给另一个对象时,我们不能保留要删除的指针。
  • @Walter。你应该阅读你引用的整个句子。特别是逗号后面的部分,我说“...只是内容已移至this 并且 rhs 可以安全销毁。

标签: c++ c++11 copy-and-swap move-assignment-operator


【解决方案1】:

“移动赋值运算符需要做什么”

我总是找到处理&& 变量的最佳方法是说“没有人关心我将这个变量置于什么状态”。你可以离开它。您可以从中复制。你可以换进去。您可以做的事情还有很多。

您的代码是正确的。 && 可以处于任何状态(只要它是可破坏的)。

对象迟早会被销毁(可能更早),实现者应该意识到这一点。如果析构函数将delete 原始指针,这一点很重要,如果相同的原始指针位于多个对象中,这将导致双重删除。

【讨论】:

  • 有时您必须让rhs 保持一致状态。例如,在 std::unique_ptr 的移动 c'tor 和分配中,您必须明确地将 rhs.ptr 设置为 nullptr 或通过调用 rhs.release() 来防止重复删除。
  • @MartinTrenkmann,您的评论可能(无意中)暗示 unique_ptr 的 users 需要致电 release。但事实并非如此。 unique_ptr 是为了做“正确的事”。
  • @MartinTrenkmann,我认为“&& 可以处于任何状态”的评论仍然有效。但我想开发人员应该知道&& 对象将被破坏(可能很快),因此开发人员应该考虑这种破坏的副作用。
  • @MartinTrenkmann,换句话说,我试图确定您是否认为我的回答有误。如果是这样,如何改进我的答案
  • 问题是关于实现移动分配,尤其是rhs 的状态,所以我的评论是从实施者 的角度来看的。在这种情况下,您的陈述“没人关心我将这个变量留在什么状态”是不正确的。另一方面,作为某人移动或分配的用户,你是对的,你不应该关心rhs,它不再可用了,但这不是我认为的问题。
猜你喜欢
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
  • 2015-03-03
  • 2019-05-08
  • 2014-03-13
  • 1970-01-01
  • 2018-05-09
  • 2017-01-16
相关资源
最近更新 更多