【问题标题】:Why can't I call move assigment from move copy ctor?为什么我不能从 move copy ctor 调用 move assignment?
【发布时间】:2019-11-09 21:18:50
【问题描述】:

如果我可以从移动 ctor 调用移动分配操作,有时看起来可以节省时间。但是当我尝试时,它会直接将我带到常规作业:

#include <iostream>
using namespace std;

class MyClass
{
public:
    MyClass() { }
    MyClass(const MyClass& other) { /* do some stuff */ }
    MyClass(MyClass&&      other);                  //move ctor

    const MyClass& operator= (const MyClass& other);
    const MyClass& operator= (MyClass&&      other); //move =
};

MyClass::MyClass(MyClass&& other)                   //move ctor
{
    cout << "Calling move ctor\n";
    *this = other; //<<--THIS IS THE PROBLEM
}

const MyClass& MyClass::operator= (MyClass&& other) //move =
{
    cout << "Calling move =\n";
    return *this;
}

const MyClass& MyClass::operator= (const MyClass& other)
{
    cout << "Calling standard =\n";
    if (this == &other) return *this;
    return *this;
}

MyClass makeVectorToTestMoveCtor() { MyClass V; return V; }

int main ()
{
    MyClass V = makeVectorToTestMoveCtor();

    return 0;
}

我可以用 std::move: 强制它

    cout << "Calling move ctor\n";
    *this = std::move(other); 

...但如果这不是一个坏主意,我肯定不需要强迫它吗?我应该在这里做什么?

【问题讨论】:

    标签: c++17 move-semantics


    【解决方案1】:

    这是一个坏主意 - 赋值的语义是关于改变现有对象的状态以使其与另一个对象匹配。存在构造函数来初始化以前不存在的对象。

    此外,您不能使用成员初始化列表来初始化成员,这要求您的数据成员是默认可构造的且非const。

    如果有的话,根据构造函数定义赋值会更有意义,例如:

    foo& foo::operator=(foo&& rhs)
    {
        this->~foo();
        new (this) foo{std::move(rhs};
    }
    

    对于上面的sn-p,需要注意不要触发UB,不过:Placement new and assignment of class with const member


    一般来说,除非您可以让编译器为您生成它们,否则我只会分别定义这两个运算符。

    【讨论】:

    • 不要那样做(先销毁再构建)。这不是异常安全的。进行自分配时也可能会损坏。
    • @Nevin:我不提倡这样做,我是说根据构造函数而不是相反的方式定义赋值更有意义。我发布的链接显示,destroy+placement new 确实很危险。我的最后一句话主张手动定义这两个函数,或者遵循零规则
    【解决方案2】:

    构造是更基本的操作。您必须先有一个构造对象,然后才能分配给它或从它分配。用构造的方式写你的作业,而不是反过来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-24
      • 2015-04-20
      • 2013-08-18
      • 2022-11-02
      • 1970-01-01
      • 2021-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多