Подтвердить что ты не робот

Возвращение константной ссылки на локальную переменную из функции

У меня есть несколько вопросов по возвращению ссылки на локальную переменную из функции:

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
}

Мои вопросы =>

  1. Правильна ли реализация getA1()? Я чувствую, что это неверно, так как он возвращает адрес локальной переменной или временный.

  2. Какое из утверждений в main (1,2,3) приведет к неопределенному поведению?

  3. В const A& newA1 = getA1(); гарантирует ли стандарт, что временная привязка константной ссылкой не будет уничтожена, пока ссылка не выйдет из области видимости?

4b9b3361

Ответ 1

1. Правильно ли реализация getA1()? Я считаю, что это неверно, поскольку он возвращает адрес локальной переменной или временный.

Единственная версия getAx(), которая правильна в вашей программе, - getA3(). Оба других имеют поведение undefined независимо от того, как вы их используете позже.

2. Какое из утверждений в главном (1,2,3) приведет к поведению undefined?

В некотором смысле ни один из них. Для 1 и 2 поведение undefined является результатом тел функций. Для последней строки newA3 должна быть компиляционной ошибкой, так как вы не можете привязать временную ссылку к не const.

3. В const A& newA1 = getA1(); стандарт гарантирует, что временная привязка к constссылка не будет уничтожена до тех пор, пока ссылка не выйдет из области видимости?

Нет. Ниже приведен пример:

A const & newConstA3 = getA3 ();

Здесь getA3() возвращает временное, а время жизни этого временного объекта привязано к объекту newConstA3. Другими словами, временное существо будет существовать до тех пор, пока newConstA3 не выйдет из области видимости.

Ответ 2

Q1: Да, это проблема, см. ответ на Q2.

Q2: 1 и 2 undefined, поскольку они относятся к локальным переменным в стеке getA1 и getA2. Эти переменные выходят за рамки и больше не доступны, и хуже может быть перезаписано, поскольку стек постоянно меняется. getA3 работает, поскольку копия возвращаемого значения создается и возвращается вызывающему.

Q3: Нет такой гарантии, чтобы видеть ответ на Q2.

Ответ 3

Я думаю, главная проблема заключается в том, что вы не возвращаете временные рамки вообще, вы должны

return A(5);

а не

A a(5);
return a;

В противном случае вы возвращаете адрес локальной переменной, а не временный. И временная ссылка на const ссылается только на временные.

Я думаю, его объяснение здесь: временная ссылка на const

Ответ 4

Если вы скомпилируете это на 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;

}