Возврат локального объекта примитивного типа и структуры

Получение ссылки на временную переменную:

struct S
{
    S() = default;
    S(const S& other) = delete;
    S(S&& other) = delete;

    ~S(){}
};

S foo1()
{
    return {}; // RVO (???)
}

int foo2()
{
    return 42; // RVO
}

int main()
{
    S& i = foo1(); // compiles!
    int& i2 = foo3(); // error C2440: 'initializing' : cannot convert from 'int' to 'int &'
}

Я знаю о продлении срока службы с const спецификатор. И понятно почему foo2 выдает ошибку. Но почему foo1 работает?

PS: протестировано с VS2013/15

2 ответа

Решение

Компиляция со всеми включенными предупреждениями (/Wall), вы случайно получаете следующее:

source_file.cpp (22): предупреждение C4239: использовано нестандартное расширение: "инициализация": преобразование из "S" в "S &"

gcc 4.9.3 std= C++14 не нравится ни одна из инициализаций.

Если мы изменим foo1() в

S foo1()
{
    S s;
    return s; 
}

Также жалуется на удаленный ход ctor. Я не уверен, почему оригинальный код не нужен.

Cppreference гласит: "Даже когда удаление копии происходит, а конструктор копирования / перемещения не вызывается, он должен присутствовать и быть доступным (как если бы оптимизация вообще не происходила), в противном случае программа плохо сформирована".

В стандарте 12,8 / 32:

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

Я понимаю, что это примечание относится к поиску правильного конструктора перемещения (первая попытка) или копирования (вторая попытка), а не другого.

Другие вопросы по тегам