Вы сбиты с толку тем фактом, что инициализация с помощью конструктора перемещения является частным случаем «инициализации копии» и не является отдельной концепцией. Проверьте примечания на странице cppreference.
Если other является выражением rvalue, конструктор перемещения будет выбран при разрешении перегрузки и вызван во время инициализации копирования. Нет такого термина, как инициализация перемещения.
Для возврата значения из функции проверьте описание возврата по cppreference . В поле указано «автоматическое c перемещение от локальных переменных и параметров», где выражение относится к тому, что вы возвращаете (предупреждение: эта цитата сокращена! Полные сведения о других случаях см. В оригинале) :
Если выражение - это id-выражение (возможно, заключенное в скобки), которое именует переменную, тип которой [...] является энергонезависимым типом объекта [...] и эта переменная объявляется [...] в теле или как параметр функции [...], затем разрешение перегрузки для выбора конструктора, используемого для инициализации возвращаемого значения, выполняется дважды: сначала, как если бы выражение было выражение rvalue (таким образом, оно может выбрать конструктор перемещения), и если первое разрешение перегрузки не удалось [...], то разрешение перегрузки выполняется как обычно, с выражением, рассматриваемым как lvalue (так что оно может выбрать конструктор копирования).
Таким образом, в особом случае возврата локальной переменной переменную можно рассматривать как r-значение, даже если нормальное s Правила yntacti c сделают его l-значением. Суть правила заключается в том, что после возврата вы не можете узнать, было ли значение локальной переменной уничтожено во время копирования-инициализации возвращенного значения, поэтому его перемещение не причиняет никакого вреда.
Относительно вашего второго вопроса: Считается плохим стилем использовать std::move
при возврате , потому что перемещение все равно произойдет, и это запрещает NRVO .
Цитата из основных руководящих принципов C ++, указанных выше:
Никогда не пишите return move(local_variable);
, потому что язык уже знает, что переменная является кандидатом на перемещение. Запись move
в этом коде не поможет и может нанести вред, поскольку на некоторых компиляторах это мешает RVO (оптимизации возвращаемого значения), создавая дополнительный псевдоним ссылки на локальную переменную.
Таким образом, код библиотеки, который вы цитируете, является неоптимальным. все еще виден после возврата функции. В цитате из cppreference важным моментом является «энергонезависимый объект тип». Когда вы возвращаете std::string& param
, это переменная с типом ссылка .