Почему не вызывается конструктор перемещения?

Я новичок в 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()), как в случае с конструктором перемещения)?

Большое спасибо!

Этот вопрос задают очень часто. Вы проверяли другие посты?

πάντα ῥεῖ 11.12.2020 18:56

«Я предпочитаю ответ Реми Лебо ниже». Хорошо, но я закрываю ваш вопрос как дубликат, чтобы другие исследователи в будущем имели возможность найти ссылку на этот дубликат (у которого есть еще несколько ответов).

πάντα ῥεῖ 11.12.2020 19:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
303
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Почему 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 при вызове оператора присваивания перемещения.

Другие вопросы по теме

Семантика перемещения C++ и вызов функции
Удаленный конструктор перемещения в базовом классе не останавливает возврат объекта производного класса из функции
Почему этот код может отключить семантику перемещения и исключение копирования?
Std::move и время жизни временных объектов
Изменение размера вектора с назначением перемещения: тип результата должен быть конструируемым из типа ввода
Когда полагаться на RVO и семантику перемещения в C++?
Эффективное использование std::move для агрегирования всех экземпляров объектов в стандартном контейнере
Безопасно ли присваивать новое значение объекту, который был перемещен, и использовать этот объект дальше?
Как создать запрос и использовать данные из асинхронного запроса?
Есть ли техническая причина, по которой цикл for на основе диапазона не определяет, зацикливается ли он на rvalue?