Разрешено ли копирование/перемещение при возврате * и объекта?

Посмотрите на этот код:

#include <stdio.h>

struct Foo {
    Foo() { }
    Foo(const Foo &) { printf("copy\n"); }
    Foo(Foo &&) { printf("move\n"); }
};

Foo getFoo() {
    Foo f;
    return *&f;
}

int main() {
    getFoo();
}

С++ 14 Standard говорит (12.8/31), что разрешено копирование/перемещение:

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

В моем примере выражение return не является именем, поэтому я не думаю, что разрешение разрешено.

Я проверил GCC/clang/MSVC, и пока clang/MSVC не выдаёт копию, GCC делает. Здесь GCC нарушает стандарт?

Ответы

Ответ 1

Во-первых, правило "as-if" здесь не применяется, потому что ваши конструкторы копирования и перемещения имеют побочные эффекты (они выполняют IO). Таким образом, GCC не может перемещать копию/перемещение под этим заголовком.

С быстрым взглядом я не вижу никаких других формулировок, которые позволяли бы эликсировать, поэтому я думаю, что это ошибка в GCC. С другой стороны, мне бы очень хотелось, чтобы стандарт расширил рамки копирования/перемещения, чтобы включить этот случай. (В минимальном примере, который вы представили, я не вижу, как это вызовет проблемы - я полагаю, у вас есть большой пример, где он это делает.)