2016-01-27 2 views
1

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

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

+0

'S & i = foo()' не следует компилировать. 'foo' возвращает временные и временные не могут быть привязаны к неконстантным ссылкам. – emlai

+0

Забавный, я думаю, что он не должен компилироваться на нескольких фронтах - даже если копия ctor никогда не выполняется, она все равно должна присутствовать, если S возвращается значением, не так ли? –

+0

С другой стороны, компилятор, вероятно, может оптимизировать весь исполняемый файл в NOP под правилом as-if. –

ответ

1

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

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

1

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

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

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

Он также жалуется на удаленные перемещения CTOR. Я не уверен, почему исходный код не нужен.

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

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

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

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

+0

Как упоминалось в комментариях, это нестандартное расширение. – nikitablack

+0

@nikitablack Моя формулировка была неясной - я имел в виду, почему gcc (и VC++) не нуждается в рабочем движении ctor, чтобы вернуть временный код в исходный код. –

+0

Это называется Оптимизация возвращаемого значения (RVO или NRVO). – nikitablack

 Смежные вопросы

  • Нет связанных вопросов^_^