Pregunta

¿Por qué esto:

#include <string>
#include <iostream>
using namespace std;

class Sandbox
{
public:
    Sandbox(const string& n) : member(n) {}
    const string& member;
};

int main()
{
    Sandbox sandbox(string("four"));
    cout << "The answer is: " << sandbox.member << endl;
    return 0;
}

Dar salida:

La respuesta es:

En lugar de:

La respuesta es: cuatro

¿Fue útil?

Solución

Sólo locales referencias const prolongar la vida útil.

El previsto por la norma tal comportamiento en §8.5.3 / 5, [dcl.init.ref], la sección sobre inicializadores de declaraciones de referencia. La referencia en su ejemplo está obligado a n argumento del constructor, y deja de ser válido cuando el n objeto está obligado a sale del ámbito.

La extensión de vida no es transitivo a través de un argumento de la función. §12.2 / 5 [class.temporary]:

El segundo contexto es cuando una referencia está unido a un temporal. El temporal a la que se une la referencia o el temporal que es el objeto completa a un subobjeto de los cuales el temporal se persiste con destino a la vida útil de la de referencia, excepto como se especifica a continuación. Un temporal unido a un miembro de referencia en ctor-inicializador de un constructor (§12.6.2 [class.base.init]) persiste hasta las salidas constructor. Un temporal unido a un parámetro de referencia en una llamada de función (§5.2.2 [expr.call]) persiste hasta la terminación de la expresión completa que contiene la llamada.

Otros consejos

Esta es la forma más sencilla de explicar lo que pasó:

En el main () que crea una cadena y se la pasó al constructor. Esta instancia de cadena sólo existía dentro del constructor. Dentro del constructor, miembro de que ha asignado a apuntar directamente a esta instancia. Cuando cuando alcance dejó el constructor, la instancia de cadena fue destruido, y miembro luego señaló a un objeto de cadena que ya no existía. Tener punto Sandbox.member a una referencia fuera de su alcance no dará por aquellas instancias externas en su alcance.

Si desea corregir su programa para mostrar el comportamiento que usted desea, realizar los siguientes cambios:

int main()
{
    string temp = string("four");    
    Sandbox sandbox(temp);
    cout << sandbox.member << endl;
    return 0;
}

Ahora temp pasará fuera de alcance al final de main () en lugar de al final del constructor. Sin embargo, esta es una mala práctica. Su variable miembro nunca debe ser una referencia a una variable que existe fuera de la instancia. En la práctica, nunca se sabe cuando esa variable irá fuera del ámbito.

Lo que recomiendo es definir Sandbox.member como const string member; Esto copiará los datos del parámetro temporal en la variable miembro en lugar de asignar la variable miembro como el parámetro temporal en sí.

En términos técnicos, este programa no está obligado a nada en realidad de salida a la salida estándar (que es una corriente tamponada para empezar).

  • El bit cout << "The answer is: " emitirá "The answer is: " en el tampón de stdout.

  • A continuación, el bit << sandbox.member suministrará la referencia colgando en operator << (ostream &, const std::string &), que invoca comportamiento indefinido .

Debido a esto, no se garantiza nada a suceder. El programa puede trabajar bien en apariencia o incluso se puede bloquear sin rubor la salida estándar - es decir, el texto "La respuesta es:". No llegaría a aparecer en la pantalla

Debido a que su cadena temporal salió del alcance una vez que el constructor de recinto de seguridad volvió, y la pila ocupado por fue reclamado para algunos otros fines.

En general, nunca debe retener referencias a largo plazo. Las referencias son buenas para los argumentos o variables locales, nunca miembros de la clase.

que usted se refiere a algo que ha desaparecido. El siguiente trabajo

#include <string>
#include <iostream>

class Sandbox
{

public:
    const string member = " "; //default to whatever is the requirement
    Sandbox(const string& n) : member(n) {}//a copy is made

};

int main()
{
    Sandbox sandbox(string("four"));
    std::cout << "The answer is: " << sandbox.member << std::endl;
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top