Comparación entre referencias y punteros en C++
La referencia es un concepto en C++; los principiantes tienden a confundir las referencias con los punteros.
En el siguiente programa, n es una referencia de m, y m es el referente.
int m; int &n = m;
n equivale a un alias (apodo) de m; cualquier operación sobre n es una operación sobre m.
Por lo tanto, n no es una copia de m, ni un puntero a m; en realidad, n es m mismo.
Reglas de las referencias:
- (1) Una referencia debe ser inicializada en el momento en que se crea (un puntero puede ser inicializado en cualquier momento).
- (2) No puede haber referencias NULL; una referencia debe estar asociada con una unidad de almacenamiento válida (un puntero puede ser NULL).
- (3) Una vez que una referencia es inicializada, no puede cambiar su relación de referencia (un puntero puede cambiar el objeto al que apunta en cualquier momento).
En el siguiente programa de ejemplo, k se inicializa como una referencia de i.
La sentencia k = j no puede modificar k para convertirla en una referencia de j, solo cambia el valor de k a 6.
Dado que k es una referencia de i, el valor de i también se convierte en 6.
int i = 5; int j = 6; int &k = i; k = j; // k 和 i 的值都变成了 6;
La función principal de las referencias es pasar parámetros y valores de retorno de funciones.
En el lenguaje C++, hay tres formas de transmitir parámetros y valores de retorno de funciones: paso por valor, paso por puntero y paso por referencia.
El siguiente es un programa de ejemplo de "paso por valor".
Debido a que x dentro de la función Func1 es una copia de la variable externa n, cambiar el valor de x no afecta a n, por lo que el valor de n sigue siendo 0.
void Func1(int x)
{
x = x + 10;
}
...
int n = 0;
Func1(n);
cout << "n = " << n << endl; // n = 0
El siguiente es un programa de ejemplo de "paso por puntero".
Debido a que x dentro de la función Func2 es un puntero a la variable externa n, cambiar el contenido del puntero provocará un cambio en el valor de n, por lo que el valor de n se convierte en 10.
void Func2(int *x)
{
(* x) = (* x) + 10;
}
...
int n = 0;
Func2(&n);
cout << "n = " << n << endl; // n = 10
El siguiente es un programa de ejemplo de "paso por referencia".
Debido a que x dentro de la función Func3 es una referencia a la variable externa n, x y n son la misma cosa; cambiar x equivale a cambiar n, por lo que el valor de n se convierte en 10.
void Func3(int &x)
{
x = x + 10;
}
...
int n = 0;
Func3(n);
cout << "n = " << n << endl; // n = 10
Al comparar los tres programas de ejemplo anteriores, se encontrará que el "paso por referencia" tiene propiedades similares al "paso por puntero", pero su forma de escritura es similar al "paso por valor".
En realidad, cualquier cosa que pueda hacer una "referencia", un "puntero" también puede hacerla. ¿Por qué entonces se necesita la "referencia"?
La respuesta es: "Usa la herramienta adecuada para hacer el trabajo adecuado".
Los punteros pueden manipular cualquier cosa en la memoria sin restricciones; aunque son muy poderosos, también son muy peligrosos.
Si realmente solo se necesita tomar prestado el "alias" de un objeto, entonces se debe usar "referencia", en lugar de "puntero", para evitar accidentes.