вопрос о функции, возвращающей ссылку в C ++ - PullRequest
7 голосов
/ 01 сентября 2010

Можно ли возвращать ссылку на локальную переменную из функции?Под локальным я подразумеваю, что переменная будет создана (в стеке, то есть без использования new) внутри функции, и ее область действия находится только внутри этой функции.Я получил противоречивые ответы, когда искал об этом.1) говорит, что вид использования является правильным, но 2) противоречит ему.

1) http://functionx.com/cpp/examples/returnreference.htm
2) http://www.cprogramming.com/tutorial/references.html (в разделе «Ссылки и безопасность»)

Кто из них прав?

Другой вопрос, который у меня возник, заключается в том, что если 1) верно, то следующие цели служат той же цели.

i) int & a = func ();
ii) int a = func ();где func () возвращает ссылку на int (локальную переменную в этой функции).

В обоих вышеописанных случаях копирование возвращаемого значения не происходит, не так ли.Я хотел бы предотвратить копирование возвращаемых значений, поскольку возвращаемое значение может быть большим.

Заранее спасибо.

Рагхава.

Ответы [ 6 ]

6 голосов
/ 01 сентября 2010

Как говорят все остальные, не делайте этого.Возвращать ссылку или указатель на локальную переменную всегда неправильно, потому что сам акт возврата избавляет от локальной переменной и, следовательно, ссылка или указатель автоматически становятся недопустимыми.

Копирование не может быть проблемой.Компиляторам C ++ разрешается пропускать конструкторы копирования при возврате из функций («оптимизация возвращаемого значения»), поэтому достаточно умный компилятор может построить это значение на месте.Следовательно, вы вполне можете вернуть большое значение без копирования.Попробуйте и посмотрите;вы можете временно поместить выходные операторы в конструктор копирования (если вы написали один и не используете автоматически сгенерированный), чтобы увидеть, действительно ли он вызывается.

Итак, без запуска и попытки вы нене знаю, происходит ли фактическое копирование, и если да, то какая это большая проблема.Как всегда, время и профиль запуска, чтобы увидеть, если есть проблема и, если так, где.Делать что-либо рискованное и / или сбивающее с толку для ускорения производительности почти никогда не стоит делать до определения времени и профилирования.

6 голосов
/ 01 сентября 2010

Вы можете вернуть ссылку на статическую локальную переменную в функции. В противном случае это может привести к катастрофе, потому что локальная переменная уничтожается после возврата из функции.

После может оказаться полезным тот же пример, который вы привели в своей первой ссылке.

РЕДАКТИРОВАТЬ 2:

Для пункта ii в вашем посте, давайте предположим функцию 'fn', как показано

int& fn(){
static int x;
return x;
}

int a = fn();

Это включает в себя копию от Lvalue выражения 'fn'.

Не включает в себя копию, если это было

int &a = fn();
5 голосов
/ 01 сентября 2010

Если вы имеете в виду переменную, внутреннюю для функции, нет ... возвращать ссылку на нее всегда глупо.Возврат ссылки на переменную-член из функции-члена - это прекрасно.

Что касается желания избегать копирования больших структур данных.Подождите, пока у вас не появятся фактические данные профиля, показывающие, что вы а) действительно делаете копию и б) что это на самом деле узкое место.«Преждевременная оптимизация - корень всего зла», может быть немного экстремальным, но преждевременная оптимизация, безусловно, вызывает много боли и неприятностей, хотя редко, если вообще когда-либо, дает ЛЮБОЕ из преимуществ, которые эти попытки предназначены достичь.

4 голосов
/ 01 сентября 2010

Примеры, которые вы видите по своей первой ссылке, полностью поддельные. Эта страница на functionx.com является мусором. Возвращение ссылки на локальную (автоматическую) переменную всегда является ошибкой, поскольку любые попытки получить доступ к возвращенному значению приведут к неопределенному поведению.

Вторая ссылка делает все правильно.

2 голосов
/ 01 сентября 2010

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

Хотя это может показаться «работающим» в первом примере, представленном в 1), эта плохая практика быстро начнет подводить вас с классами, которые имеют деструктор или больше.

Лучше всего либо вернуть указатель, вернуть ссылку на локально-статический объект, вернуть ссылку на переменную-член.

В этом случае, если объект создается внутри возвращаемой функции, вы можете изучить реализацию семантики перемещения C ++ 0x в вашем большом классе. Это может превратить «большую копию» в несколько замен указателей.

0 голосов
/ 01 сентября 2010

при условии, что func возвращает ссылку на значение, которое живет после возврата функции (статической локальной или глобальной), а затем

i) int& a = func();
ii) int a = func(); where func() returns a reference to an int (local variable in that function).

совсем другие

в (i) все еще относится к статическому или глобальному. Изменение изменит исходную переменную

в (ii) a является локальной копией, изменение которой не влияет на исходную переменную

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...