Volviendo referencia constante a la variable local de una función
-
13-09-2019 - |
Pregunta
Tengo algunas preguntas sobre el retorno de una referencia a una variable local de una función:
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
}
Mis preguntas son =>
-
Es la aplicación de
getA1()
correcta? Siento que es incorrecto, ya que es devolver la dirección de una variable local o temporal. -
¿Cuál de las declaraciones en
main
(1,2,3) dará lugar a un comportamiento indefinido? -
En
const A& newA1 = getA1();
Qué garantiza la norma de que un temporal vinculado por una referencia const no será destruido hasta que la referencia se sale del ámbito?
Solución
1. ¿Es correcta aplicación
getA1()
? Siento que es incorrecta, ya que está devolviendo la dirección de la variable local o temporal.
La única versión de getAx()
que es correcto en su programa es getA3()
. Ambos de los otros han indefinido comportamiento no importa cómo se utilicen más tarde.
2. ¿Cuál de las declaraciones en principal (1,2,3) dará lugar a un comportamiento indefinido?
En un sentido ninguno de ellos. Para 1 y 2 el comportamiento indefinido es como resultado de los cuerpos de las funciones. Para la última línea, newA3
debe ser un error de compilación como no se puede obligar a un temporal a una referencia no const.
3. En
const A& newA1 = getA1();
hace garantías estándar que encuadernados temporal por unconst
referencia no será destruido hasta que la referencia se sale del ámbito?
No. El siguiente es un ejemplo de que:
A const & newConstA3 = getA3 ();
A continuación, getA3()
devuelve un temporal y el tiempo de vida de ese temporal está ahora unido al newConstA3
objeto. En otras palabras, el temporal existirá hasta que newConstA3
sale del ámbito.
Otros consejos
P1:. Sí, esto es un problema, véase la respuesta a la Q2
Q2: 1 y 2 están indefinidos ya que se refieren a las variables locales en la pila de getA1 y getA2. Estas variables salen del alcance y ya no están disponibles y se pueden sobrescribir peor que la pila está en constante cambio. getA3 funciona ya que se crea y se devuelve al llamador una copia del valor de retorno.
P3: No existe tal garantía para ver la respuesta a la Q2
.Creo que el problema principal es que no se está devolviendo los temporales en absoluto, usted debe
return A(5);
en lugar de
A a(5);
return a;
De lo contrario va a devolver dirección de la variable local, no temporal. Y el temporal a const referencia solamente funciona para los temporales.
Creo que se explica aquí: temporal a const referencia
Si va a compilar esto en VC6 obtendrá esta advertencia
****** Advertencia del compilador (nivel 1) C4172 la dirección de vuelta de la variable local o temporal Una función devuelve la dirección de un objeto o variable temporal local. Las variables locales y objetos temporales se destruyen cuando devuelve una función, por lo que la dirección de retorno no sea válida. ******
Durante la prueba para este problema que encontré algo interesante (código dado está trabajando en 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;
}