Почему я не могу вызвать задание перемещения из ctor-копии? - PullRequest
0 голосов
/ 27 июня 2019

Иногда кажется, что это экономит время, если я могу вызвать опцию назначения перемещения из 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); 

... но если это не плохая идея, конечно, мне не нужно ее форсировать? Что мне здесь делать?

Ответы [ 2 ]

0 голосов
/ 28 июня 2019

Строительство является более фундаментальной операцией. Вы должны иметь построенный объект, прежде чем вы сможете назначить или из него. Напишите свое задание с точки зрения конструкции, а не наоборот.

0 голосов
/ 27 июня 2019

Это плохая идея - семантика присваивания заключается в изменении состояния существующего объекта, чтобы он соответствовал другому.Существует конструктор для инициализации объекта, который ранее не существовал.

Кроме того, вы не можете инициализировать элементы с помощью списка инициализации элементов , который требует, чтобы ваши элементы данных были конструируемыми по умолчанию и не- const.

Во всяком случае, было бы более целесообразно определить присваивание в терминах конструктора, например:

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

Для приведенного выше фрагмента необходимоосторожно, чтобы не вызывать UB, хотя: Размещение нового и присвоение класса с константным членом


В общем, я бы просто определил оба оператора по отдельности, если вы не можете позволить компилятору генерировать ихдля вас.

...