Есть ли разница между этими формами: returnType и returnType &? - PullRequest
4 голосов
/ 02 июня 2011

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

          std::vector<int>& f();   //reference
          std::vector<int>  g();   //value

/*const*/ std::vector<int>&  f1 = f();  //reference
          std::vector<int>   f2 = f();  //value

/*const*/ std::vector<int>&  g1 = g();  //reference
          std::vector<int>   g2 = g();  //value

Есть ли разница между:

  • f () и g ().Это простой вопрос, но все же я хотел бы услышать некоторые подробные комментарии к ним, поскольку это может помочь понять ответ на следующие вопросы.

  • f1 и f2.Будут ли они такими же оригинальными объектами из f (), или f2 будет копией оригинала?Раскомментирование const будет иметь значение?

  • g1 и g2.Будут ли они одним и тем же исходным объектом из g (), или g2 будет копией оригинала?Раскомментирование const будет иметь какое-либо значение?

Что если f() и g() являются функциями-членами, и каждый возвращает данные члена, а не некоторую локальную переменную?Будет ли это иметь какое-либо значение в ответе на вышеуказанные вопросы?

Пожалуйста, попробуйте включить в свой ответ все подводные камни и важные моменты, и не учитывайте RVO или любую другую оптимизацию компилятором.Я хочу знать, что такое C ++, а не то, что делают компиляторы.Если вы говорите об оптимизации, пожалуйста, упомяните об этом явно, чтобы я не смешивал возможности языка с функциями компилятора.

1 Ответ

8 голосов
/ 02 июня 2011

f() возвращает ссылку на объект;возвращение из него не копирует какой-либо объект.g() возвращает копию объекта, по крайней мере, концептуально.

std::vector<int>&  f1 = f();  //reference

f1 относится к объекту, на который f() вернул ссылку.Копии не сделаны.Константная квалификация ссылки здесь не имеет значения (что касается копирования; очевидно, это влияет на то, что можно сделать с объектом).

std::vector<int>   f2 = f();  //value

f2 является копией объектана который f() возвращена ссылка.

std::vector<int>&  g1 = g();  //reference

Это недопустимо.Неконстантная ссылка не может быть связана с временным объектом.

Если ссылка является константно-квалифицированной, то эта строка фактически совпадает со следующей строкой: создается копия объекта, возвращенного g(), ссылка привязывается к этой копии, и эта копиязадается время жизни ссылки (оно уничтожается, когда ссылка «уничтожается»).

std::vector<int>   g2 = g();  //value

g2 - это копия объекта, возвращаемая g().Будет ли сделана копия (и сколько копий может быть сделано), зависит от оптимизации компилятора.

Что если f() и g() являются функциями-членами, и каждый возвращает данные члена, а не какие-то локальныепеременная?

Если f() возвращает ссылку на локальную переменную, программа неверна и выдает неопределенное поведение, если вы пытаетесь использовать ссылку, потому что указанный объект перестает существовать, когда функция возвращается.

Если f() возвращает ссылку на переменную-член, динамически размещенный объект или объект со статической или потоковой локальной памятью, тогда ссылка действительна в течение всего времени жизни этого объекта (или другого объекта).того же типа, созданного в том же месте в памяти, что и объект, на который была возвращена ссылка, хотя полезность этого ограничена несколькими выбранными сценариями).

Неважно, что g()возвращается, потому что копия всегда создается (по крайней мере, концептуально).

...