2011-07-31 27 views
10

Siento que esta pregunta es lo suficientemente básica como para estar por ahí en alguna parte, pero parece que no puedo encontrar una respuesta para ella.Declarando una referencia al objeto y al operador de asignación

Supongamos que tengo este código:

//class member function 
std::map< std::string, std::string > myMap; 

const std::map< std::string, std::string >& bar() 
{ 
    return myMap; 
} 

void myFunc(std::map< std::string, std::string >& foo1) 
{ 
    foo1 = bar(); 
    std::map< std::string, std::string >& foo2 = bar(); 
} 

Mi opinión es que si empiezo a usar foo2, ya foo2 es una referencia a la misma instancia que lo bar() regresa, cualquier cosa que hago con foo2 será reflejado en myMap. ¿Pero qué hay de foo1? ¿Foo1 obtiene una copia de myMap o también apunta a la misma instancia que devuelve bar()? La biblioteca estándar de C++ dice que el operador de asignación para std :: map copiará los elementos, pero ¿significa eso que el operador de asignación realmente no se invoca en la declaración de foo2?

Gracias!

Respuesta

15

Las referencias no se pueden volver a seleccionar en C++. Esto significa que una vez que se inicializan, no puede reasignarlos. En cambio, cualquier asignación en realidad implica el objeto referido. Así que en su código,

foo1 = bar(); 
std::map< std::string, std::string >& foo2 = bar(); 

la primera línea llama std::map::operator= en el objeto que se pasa como parámetro a myFunc. Después de eso, foo1 imágenes fijas se refiere a ese mismo objeto, pero su valor (por ejemplo, qué elementos contiene) puede haber cambiado.

Tenga en cuenta que la segunda línea es asignación no si alguna vez hubo alguna duda de que estaba en su mente. En cambio, es una inicialización. Como el tipo de retorno de la barra es en realidad std::map<std::string, std::string> const&, no se puede vincular a std::map<std::string, std::string>&, por lo que es un error de compilación.


Para ampliar en el lado 'filosófica' de las cosas, las referencias de C++ están diseñados para ser lo más transparente posible y no existen realmente como objetos. Esto está utilizando el significado estándar de C++ del término (no está relacionado con OOP): significa que, por ejemplo, los tipos de referencia tienen un tamaño. En cambio, sizeof(T&) == sizeof(T). Del mismo modo, las referencias no tienen direcciones y no es posible formar un puntero o una referencia a una referencia: dado int& ref = i;, entonces &ref == &i.

Las referencias están destinadas deliberadamente a ser utilizadas como si los objetos referidos se estuvieran utilizando. Lo único específico de referencia que ocurre en la vida de una referencia es su inicialización: a qué se puede vincular y qué significa en términos de tiempo de vida.

+0

+1 Gracias, aprendí algo nuevo por mi cuenta. Acabo de hacer una prueba y estaba 100% INCORRECTO y tienes razón = -) – flumpb

+0

Ok, genial! Gracias, lo que realmente necesitaba saber es que el operador de asignación se invoca en foo1 y no se invoca en foo2. Gran explicación, gracias! – bhh1988

+0

@Luc Si es posible, ¿puede repasar por qué las variables de referencia generalmente no se usan?Tengo una mejor comprensión de lo que son (gracias a su respuesta) pero parece que los codificadores en general están a favor de los indicadores al respecto. ¿Es la redundancia? El alcance limitado? –

0

La línea

foo1 = bar(); 

crea una copia (porque eso es lo que hace el operador de asignación map 's).

+0

parece extraño devolver una referencia a una variable global, ¿no? –

+0

@ 0A0D: No realmente, se puede usar para encapsulación, si la variable "global" no tiene enlaces externos. O puede devolver una referencia a la variable global 'a' o a la variable global' b'. –

Cuestiones relacionadas