2012-02-29 20 views
17

Decidí ver si la asignación de una referencia a un miembro haría referencia a un miembro. Escribí el siguiente fragmento para probarlo. Hay una clase simple Wrapper con un std::string como variable miembro. Tomo tomar un const string& en el constructor y asignarlo a la variable miembro pública. Más adelante, en el método main(), modifico la variable miembro pero el string que pasé al constructor permanece sin cambios, ¿cómo es posible? Creo que en Java la variable habría cambiado, ¿por qué no en este fragmento de código? ¿Cómo funcionan exactamente las referencias en este caso?Pasando por referencia a un constructor

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

class Wrapper 
{ 
public: 
    string str; 

    Wrapper(const string& newStr) 
    { 
     str = newStr; 
    } 
}; 

int main (int argc, char * const argv[]) 
{ 
    string str = "hello"; 
    cout << str << endl; 
    Wrapper wrapper(str); 
    wrapper.str[0] = 'j'; // should change 'hello' to 'jello' 
    cout << str << endl; 
} 
+2

Los tipos en C++ son lo que decretas, y no se convierten mágicamente en otra cosa. Dices 'string', y obtienes una' cadena'. Si quisieras una referencia, hubieras dicho 'string &'. –

+0

Abusaste de personas con una pregunta demasiado simple :) – Mikhail

+2

En Java, la variable no habría cambiado porque el código ni siquiera se habría compilado; las cadenas en Java no pueden ser modificadas. –

Respuesta

22

Para asignar una referencia en un constructor es necesario tener un miembro de referencia

class A{ 
    std::string& str; 
public: 
    A(std::string& str_) 
    : str(str_) {} 
}; 

str es ahora una referencia al valor que se ha pasado. Lo mismo se aplica para los árbitros const

class A{ 
    const std::string& str; 
public: 
    A(const std::string& str_) 
    : str(str_) {} 
}; 

Sin embargo no olvide que una vez que se ha asignado una referencia, no se puede cambiar, por lo que si la asignación requiere un cambio en str, tendrá que ser un puntero.

5

Debido Wrapper::str no es una referencia, es un objeto independiente. Entonces cuando usted hace str = newStr, está copiando la cadena.

1

Debe declarar Wrapper::str como string&, no como string.

3

Es necesario utilizar un inicializador y declarar str como referencia como en:

class Wrapper { 
public: 
    string &str; 

    Wrapper(string& newStr) 
     : str(newStr) { 
    } 
}; 

La forma en que está escrito, todo lo que está haciendo es copiar el valor de la referencia se pasa a la Constuctor . No estás guardando la referencia. Al declarar una referencia como miembro de la clase e inicializarla con una referencia a otra instancia de cadena, obtendrá el comportamiento que está buscando.

+1

Tu código intenta inicializar una referencia a mutable con una referencia-a-const. –

+0

Corregido ... eso es lo que recibo por copiar ciegamente del OP. – andand

5
class Wrapper 
{ 
public: 
    string& str; 

    Wrapper(string& newStr) : str(newStr) {} 
}; 

Nota, no se puede aceptar una const string& y almacenarlo en un string&, que perdería const-corrección en hacerlo.

1

La variable principal de su cuerpo es std::string.

Su variable de parámetro es const std::string&.

La const en las referencias son siempre "const de bajo nivel", lo que significa que modifica el tipo de objeto, no el objeto real.

En contraste, un "const de nivel superior" modifica un objeto real. Lea C++ Primer on Top level const para una aclaración.

Así es como su asignación se ve como cuando se pasa argumentos:

const std::string& = std::str; //Values are ommited 
// i.e const std::string newStr = std::string str 

va a inicializar un const type reference con un non-const value que es aceptable. No debe cambiar el valor de std::string str usando esa referencia.Y, si intenta cambiar el valor de newStr dentro del constructor, obtendrá un error de compilación.

siguiente que estás haciendo otra tarea dentro del constructor que también es aceptable:

std::string = const std::string 

El hecho de que wrap.str[0] no cambió str de main es que, aunque se utilizó una referencia a una instancia de class str, class str tiene su propio objeto y no está vinculado al main str. El uso de esa referencia en un parámetro solo vincula ese parámetro al main str; no main str a class str.

Si se hizo referencia a las variables de clase, entonces podría haber cambiado.

Cuestiones relacionadas