referencias - que es un parametro en c++
¿Una referencia constante prolonga la vida de un temporal? (5)
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 de:
La respuesta es:
En lugar de:
La respuesta es: cuatro
Debido a que su cadena temporal se salió del alcance una vez que el constructor Sandbox regresó, y la pila ocupada por ella se recuperó para otros fines.
En general, nunca debe conservar referencias a largo plazo. Las referencias son buenas para argumentos o variables locales, nunca para miembros de la clase.
Esta es la forma más sencilla de explicar lo que sucedió:
En main () creó una cadena y la pasó al constructor. Esta instancia de cadena solo existía dentro del constructor. Dentro del constructor, asignó miembro para señalar directamente a esta instancia. Cuando el ámbito dejó el constructor, se destruyó la instancia de cadena y el miembro apuntó a un objeto de cadena que ya no existía. Hacer que Sandbox.member señale una referencia fuera de su alcance no mantendrá esas instancias externas dentro del alcance.
Si desea arreglar su programa para mostrar el comportamiento que desea, realice los siguientes cambios:
int main()
{
string temp = string("four");
Sandbox sandbox(temp);
cout << sandbox.member << endl;
return 0;
}
Ahora la temperatura pasará del ámbito 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 cuándo esa variable saldrá del alcance.
Lo que recomiendo es definir Sandbox.member como un 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í mismo.
Solo las referencias de const
locales prolongan la vida útil.
El estándar especifica tal comportamiento en §8.5.3 / 5, [dcl.init.ref], la sección de inicializadores de declaraciones de referencia. La referencia en su ejemplo está vinculada al argumento del constructor n
, y se vuelve inválida cuando el objeto n
está obligado a salir del alcance.
La extensión de duración no es transitiva a través de un argumento de función. §12.2 / 5 [class.temporary]:
El segundo contexto es cuando una referencia está vinculada a un temporal. El temporal al que se enlaza la referencia o el temporal que es el objeto completo de un subobjeto del cual el temporal está vinculado persiste durante el tiempo de vida de la referencia, excepto como se especifica a continuación. Un enlace temporal a un miembro de referencia en un ctor-initializer de un constructor (§12.6.2 [class.base.init]) persiste hasta que el constructor sale. Un límite temporal a un parámetro de referencia en una llamada a función (§5.2.2 [expr.call]) persiste hasta la finalización de la expresión completa que contiene la llamada.
Técnicamente hablando, este programa no es necesario para producir algo en la salida estándar (que es una secuencia amortiguada para empezar).
El
cout << "The answer is: "
bit emitirá"The answer is: "
en el buffer de stdout.A continuación, el bit
<< sandbox.member
proporcionará la referencia pendiente en eloperator << (ostream &, const std::string &)
, que invoca un comportamiento indefinido .
Debido a esto, no está garantizado que ocurra nada. El programa puede funcionar aparentemente bien o puede bloquearse sin necesidad de enjuagar el stdout, lo que significa que el texto "La respuesta es:" no aparecerá en su pantalla.
respuesta simple: te estás refiriendo a algo que se ha desvanecido. Lo siguiente funcionará
#include <string>
#include <iostream>
using namespace std;
class Sandbox
{
public:
const string member = " ";
Sandbox(const string& n) : member(n) {}//a copy is made
};
int main()
{
Sandbox sandbox(string("four"));
cout << "The answer is: " << sandbox.member << endl;
return 0;
}