Возвращаясь ссылку на локальную переменную из функции
У меня есть несколько вопросов по возвращению ссылки на локальную переменную из функции:
class A
{
public:
A(int xx):x(xx)
{
printf("A::A()n");
}
};
const A& getA1()
{
A a(5);
return a;
}
A& getA2()
{
A a(5);
return a;
}
A getA3()
{
A a(5);
return a;
}
int main()
{
const A& newA1 = getA1(); //1
A& newA2 = getA2(); //2
A& newA3 = getA3(); //3
}
Мои вопросы =>
-
Является ли реализация
getA1()
правильной? Я чувствую, что это неправильно, так как он возвращает адрес локальной переменной или временной. -
Какое из утверждений в
main
(1,2,3) приведет к неопределенному поведению? -
В
const A& newA1 = getA1();
гарантирует ли стандарт, что временная привязка к ссылке const не будет уничтожен до тех пор, пока ссылка не выйдет за рамки?
4 ответа:
1. Является ли
getA1()
реализация правильной ? Я чувствую, что это неправильно, так как это возвращает адрес локальной переменной или временной.Единственная версия
getAx()
, которая является правильной в вашей программе, - этоgetA3()
. Оба других имеют неопределенное поведение, независимо от того, как вы используете их позже.В каком-то смысле ни один из них. Для 1 и 2 неопределенное поведение имеет вид результат выполнения органами функций. Для последней строки2. Какое из утверждений в main (1,2,3) приведет к неопределенному поведению ?
newA3
должно быть ошибкой компиляции, так как вы не можете привязать временную ссылку к неконстантной ссылке.3. В
const A& newA1 = getA1();
ли стандарт гарантирует, что временная привязка кconst
ссылка не будет уничтожена до тех пор, пока ссылка не выйдет за пределы области действия?Нет. Ниже приведен пример этого:
A const & newConstA3 = getA3 ();
Здесь
getA3()
возвращает временное значение, и время жизни этого временного значения теперь привязано к объектуnewConstA3
. Другими словами, временное будет существовать до тех пор, покаnewConstA3
не выйдет за рамки.
Q1: Да, это проблема, см. ответ на Q2.
Q2: 1 и 2 не определены, поскольку они ссылаются на локальные переменные в стеке getA1 и getA2. Эти переменные выходят за пределы области видимости и больше не доступны, а хуже того, могут быть перезаписаны, поскольку стек постоянно меняется. getA3 работает, так как копия возвращаемого значения создается и возвращается вызывающему объекту.
Q3: нет такой гарантии, чтобы увидеть ответ на Q2.
Я думаю, что главная проблема заключается в том, что вы вообще не возвращаете временные данные, вы должны
return A(5);
Вместо
A a(5); return a;
В противном случае вы возвращаете адрес локальной переменной, а не временный. А временная ссылка на const работает только для временных.
Я думаю, что это объясняется здесь: временная ссылка на const
Если вы скомпилируете это на VC6, вы получите это предупреждение
******предупреждение компилятора (уровень 1) C4172 возвращаемый адрес локальной переменной или временной Функция возвращает адрес локальной переменной или временного объекта. Локальные переменные и временные объекты уничтожаются при возврате функции, поэтому возвращаемый адрес недопустим.******
Во время тестирования этой задачи я обнаружил интересную вещь (данный код работает в VC6):
class MyClass { public: MyClass() { objID=++cntr; } MyClass& myFunc() { MyClass obj; return obj; } int objID; static int cntr; }; int MyClass::cntr; main() { MyClass tseadf; cout<<(tseadf.myFunc()).objID<<endl; }