Будут ли перемещены дочерние подобъекты локальных переменных, если они возвращаются из функции? - PullRequest
7 голосов
/ 08 февраля 2012

Стандарт C ++ 11 гласит, что, если выполняются условия исключения копии (§12.8/31), реализация должна обрабатывать return ed локальную переменную lvalue и параметры функции, как rvalue first (move),и если разрешение перегрузки не удается, как подробно, то следует рассматривать его как lvalue (копию).

§12.8 [class.copy] p32

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

Включает ли это также подобъекты-члены?Я протестировал следующий фрагмент:

#include <iostream>

struct traced{
  traced(){ std::cout << "default ctor\n"; }
  traced(traced const&){ std::cout << "copy ctor\n"; }
  traced(traced&&){ std::cout << "move ctor\n"; }
};

struct X{
  traced t;
};

traced f(){
  X x;
  return x.t;
}

int main(){
  traced t = f();
}

Живой пример на Ideone. И ни в GCC 4.7 ToT, ни в Clang 3.1 ToT не будет отображаться «Move Ctor», что заставляет меня поверить, чтостандарт не включает подобъекты участников.

Я что-то пропустил?Мой тестовый код не работает?Что именно делает вывод таким, какой он есть?

1 Ответ

6 голосов
/ 08 февраля 2012

При возврате подобъекта вы не можете отказаться от его построения. Думайте об этом так: перемещение и копирование elision по существу равносильны созданию объекта в том месте, куда он в конечном итоге будет перемещен или скопирован. Это работает для законченных объектов, потому что будет выделено соответствующее пространство. Он не работает с подобъектами, потому что вы создали бы окружающий объект. Даже если он имеет тот же размер, что и подобъект, то есть достаточно места, включающий объект разрушается и может делать забавные вещи с подобъектами.

По сути, это означает, что конструкция субъекта не может быть исключена.

...