Можно ли присваивать объекту, который уже был использован в move-семантике?
1,00
р.
р.
Предположим, есть код: struct example { example() { ptr = new int(2) } example(example&& rhs) { ptr = rhs.ptr rhs.ptr = nullptr } ~example() { delete ptr } int a = 2 char b = 'a' int* ptr } int main() { example e int* a = new int(1) example move_e = std::move(e) e = {1,'b', a} } Теперь вопрос: корректно ли после перемещения объекта e опять ему присваивать что-либо? Я знаю, что обращаться к полям после перемещения будет undefined behavior, но а если что-то присваивать объекту? Всё вроде законно, и после присваивания его поля снова будет можно использовать как r-value... Прав ли я?
Ответ Безусловно можно. Есть даже пример в черновике Стандарта: T old_val = std::move(obj) obj = std::forward(new_val) return old_val Ну и сама выдержка из Стандарта про то, что представляет из себя перемещенный объект: Objects of types defined in the C++ standard library may be moved from ([class.copy]). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state. Т.е. такие объекты находятся в корректном, но неопределенном состоянии. В частности, все функции-члены такого объекта должны отрабатывать корректно, в том числе и оператор =.
Стоит обратить особое внимание, что указанная цитата относится к типам стандартной библиотеки. Для пользовательских классов программист сам задает состояние объекта после перемещения, т.к. сам же и пишет реализацию перемещающих функций.
Ссылка на ответ на enSO. При этом, чтобы Ваш код был работоспособен, требуется добавить соответствующий конструктор и оператор присваивания (в данном случае подойдет перемещающий): example(int a, char b, int* ptr) : a(a), b(b), ptr(ptr) {} example& operator=(example&& o) { a = o.a b = o.b ptr = o.ptr o.ptr = nullptr return *this }