Подтвердить что ты не робот

Возвращение объекта const из функции предотвращает перемещение конструкции извне?

Учитывая эти функции и вызов функции:

std::string GetString() {
  std::stringstream sstr;
  const auto str = sstr.str();
  return str;
}

const auto returnedStr = GetString();

Будет ли исключена конструкция move, поскольку я объявляю str как const?

4b9b3361

Ответ 1

В вашем случае returnedStr будет построено по ходу из возвращаемого значения GetString(), но это возвращаемое значение будет построено по копиям из str (1). Если str не был const, возвращаемое значение было бы построено из него.

Обратите внимание, что в обоих случаях оптимизация возвращаемого значения по-прежнему применима, поэтому компилятор может по-прежнему строить возвращаемое значение (или даже str непосредственно) в пространстве returnedStr, пропуская одну или обе копии, Это предоставляется С++ 11 12.8/31:

При выполнении определенных критериев реализация допускает опустить конструкцию копирования/перемещения класса объект, даже если конструктор copy/move и/или деструктор объекта имеют побочные эффекты. В таких случаях, реализация рассматривает источник и цель пропущенной операции копирования/перемещения как просто две разные способы обращения к одному и тому же объекту, а уничтожение этого объекта происходит в более поздние времена когда два объекта были бы уничтожены без оптимизации. Это разрешение копирования/перемещения операции, называемые копией, разрешены в следующих обстоятельствах (которые могут быть объединены с устранить несколько копий):

  • в выражении return в функции с типом возвращаемого класса, когда выражение является именем энергонезависимый автоматический объект (кроме функции или параметра catch-clause) с тем же самым cv-unqualified тип как возвращаемый тип функции, операцию копирования/перемещения можно опустить при построении автоматический объект непосредственно в функции возвращает значение

  • ...

  • когда объект временного класса, который не был привязан к ссылке (12.2), будет скопирован/перемещен к объекту класса с тем же cv-неквалифицированным типом операция копирования/перемещения может быть опущена построение временного объекта непосредственно в цель пропущенной копии/перемещения

Первая маркерная точка покрывает эллиптичность конструкции возвращаемого значения, вторая - переносит возвращаемое значение в returnedStr. Обратите внимание на требование на "тот же самый cv-unqualified", что означает, что это работает независимо от cv-классификаторов.


(1) Обратите внимание, что если бы мы говорили о классе X, отличном от std::string, который предоставил конструктор перемещения, принимающий a const X&&, тогда действительно возвращаемое значение было бы перемещение, построенное с использованием этого конструктора (независимо от его семантики).

Ответ 2

Правильный ответ правильный, но кто может запомнить все правила адвоката языка?

Чтобы помочь мне запомнить это, я написал следующие правила, которые поступали из собственного уст STL.

15) Не возвращайте locals как const [16]

$Запрещает перемещение семантики

16) Не используйте move при возврате локально по значению точно такой же тип [16]

$NVRO не будет использоваться, если вы это сделаете.

17) Не возвращайте ссылку Rvalue (&) [16]

$Если вы действительно не знаете, что делаете.

Примечания:

[16] Не помогите компилятору, Going Native 2013, http://www.youtube.com/watch?v=AKtHxKJRwp4