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 =>

  1. Es la aplicación de getA1() correcta? Siento que es incorrecto, ya que es devolver la dirección de una variable local o temporal.

  2. ¿Cuál de las declaraciones en main (1,2,3) dará lugar a un comportamiento indefinido?

  3. 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?

¿Fue útil?

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 un const   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;

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top