Я новичок в C++ и пытаюсь понять ссылки rvalue и семантику перемещения.
Я написал простой класс Class, который включает в себя метод fun, который создает экземпляр класса в своем теле и возвращает его. Класс имеет конструктор копирования, конструктор перемещения, оператор присваивания (копирования) и оператор присваивания (перемещения).
Следующее
Class obj2(obj1.fun()); // ??
obj3 = obj2.fun(); // (move) Assignment operator
не вызывает конструктор копирования или конструктор перемещения и не вызывает оператор присваивания (перемещения) соответственно.
Как создается obj2? Почему не
Class obj2(obj1.fun());
вызвать конструктор перемещения,
Class obj2(std::move(obj1.fun()));
вызывает конструктор перемещения и
obj3 = obj2.fun()
вызывает оператор присваивания (перемещения) (без необходимости писать std::move(obj2.fun())
, как в случае с конструктором перемещения)?
Большое спасибо!
«Я предпочитаю ответ Реми Лебо ниже». Хорошо, но я закрываю ваш вопрос как дубликат, чтобы другие исследователи в будущем имели возможность найти ссылку на этот дубликат (у которого есть еще несколько ответов).
Почему
Class obj2(obj1.fun());
не вызывает конструктор перемещения
Из-за Копировать Элисон. Компилятор видит, что fun()
возвращает временный объект, и этот временный объект будет использоваться только для инициализации obj2
, поэтому компилятор оптимизирует создание obj2
, полностью удаляя временный объект и позволяя создавать obj2
непосредственно внутри самого fun()
, таким образом, нет необходимости в операции копирования/перемещения при выходе fun()
.
Class obj2(std::move(obj1.fun()));
вызывает конструктор перемещения
Потому что вы форсируете его с помощью явного приведения типа std::move
, поэтому компилятор не может оптимизировать создание obj2
с помощью Copy Elison, поэтому он должен разрешить fun()
возвращать временный объект, который вы затем перемещаете в конструктор obj2
.
obj3 = obj2.fun()
вызывает оператор присваивания (перемещения)
Потому что obj3
уже существует до присваивания.
без необходимости писать
std::move(obj2.fun())
Поскольку fun()
возвращает временный объект, который является rvalue, поэтому нет необходимости явно приводить его к rvalue при вызове оператора присваивания перемещения.
Этот вопрос задают очень часто. Вы проверяли другие посты?