Имеет ли смысл возвращение с помощью `std :: move` в случае множественных операторов возврата? - PullRequest
22 голосов
/ 02 марта 2012

Я знаю, что обычно не стоит возвращаться с std::move, то есть

bigObject foo() { bigObject result; /*...*/ return std::move(result); }

вместо простого

bigObject foo() { bigObject result; /*...*/ return result; }

, потому что это мешаетоптимизация возвращаемого значения.Но что в случае функции с несколькими различными значениями возврата, в частности, что-то вроде

class bar {
  bigObject fixed_ret;
  bool use_fixed_ret;
  void prepare_object(bigObject&);
 public:
  bigObject foo() {
    if(use_fixed_ret)
      return fixed_ret;
     else{
      bigObject result;
      prepare_object(result);
      return result;
    }
  }
};

Я думаю, что нормальная оптимизация возвращаемого значения невозможна в такой функции, поэтому было бы неплохо добавить

      return std::move(result);
1013 * здесь, или я должен делать, а (IMO уродливее, но это спорный вопрос) 1015 *

1 Ответ

33 голосов
/ 02 марта 2012

Для локальных переменных нет необходимости std::move их в выражении return большую часть времени , поскольку язык фактически требует, чтобы это происходило автоматически:

§12.8 [class.copy] p32

Когда критерии для исключения операции копирования будут выполнены или будут выполнены, за исключением того факта, что исходный объект является параметром функции, и копируемый объект обозначается lvalue, для выбора разрешения перегрузки конструктор для копии сначала выполняется так, как если бы объект был обозначен значением r . Если не удается разрешить перегрузку или если тип первого параметра выбранного конструктора не является rvalue-ссылкой на тип объекта (возможно, cv-квалифицирован), разрешение перегрузки выполняется снова, рассматривая объект как lvalue. [ Примечание: Это двухэтапное разрешение перегрузки должно выполняться независимо от того, будет ли выполнено копирование. Он определяет конструктор, который будет вызван, если elision не выполняется, и выбранный конструктор должен быть доступен, даже если вызов исключен. - Конечная заметка ]


† Исключение копирования очень ограничено в том месте, где его можно применить (§12.8/31). Одним из таких ограничений является то, что тип исходного объекта должен быть таким же, как и у cv-неквалифицированного возвращаемого типа функции при работе с оператором return. Это также не применимо для подобъектов локальных переменных, которые собираются выйти из области видимости.

...