Не изменяются ли значения параметров при возврате значения?

Рассмотрим следующую функцию:

Foo foo(Foo x)
{
    return x;
}

Будет ли return x вызывать конструктор копирования или конструктор перемещения? (Оставьте NRVO в стороне отсюда.)

Чтобы исследовать, я написал простой класс Foo, который является только подвижным, но не копируемым:

struct Foo
{
    Foo() = default;
    Foo(const Foo&) = delete;
    Foo(Foo&&) = default;
};

Если конструктор перемещения был вызван при возврате значений параметров по значению, все должно быть хорошо. Но текущий компилятор g++ жалуется на return x со следующим сообщением об ошибке:

error: deleted function 'Foo::Foo(const Foo&)'

Если заменить return x на return std::move(x), все будет хорошо. Из этого я заключаю, что переход от значений параметров должен выполняться явно, если это необходимо. Соответствует ли поведение g++ или нет?

Ответ 1

Если есть перемещение ctor для Foo, оно должно быть выбрано.

Функциональные параметры явно исключены из выражения копирования в операторах возврата (FDIS §12.9p31, первая марка):

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

Однако в следующем параграфе явно приводятся соображения перемещения ctors:

Когда выполняются критерии для выполнения операции копирования или , за исключением того факта, что исходный объект является параметром функции, а подлежащий копированию объект обозначается lvalue, разрешение перегрузки для выбора конструктора для копии сначала выполняется , как если бы объект был обозначен rvalue....

(Акцент мой в обоих кавычках.)

Ответ 2

Это допустимое поведение кода-g++ является несоответствующим. MSVC10 поддерживает это поведение.