3.4.6. Introducción a las referencias de C++

Los punteros funcionan más o menos igual en C y en C++, pero C++ añade un modo adicional de pasar una dirección a una función. Se trata del paso-por-referencia y existe en otros muchos lenguajes, de modo que no es una invención de C++.

La primera impresión que dan las referencias es que no son necesarias, que se pueden escribir cualquier programa sin referencias. En general, eso es verdad, con la excepción de unos pocos casos importantes que se tratarán más adelante en el libro, pero la idea básica es la misma que la demostración anterior con el puntero: se puede pasar la dirección de un argumento utilizando una referencia. La diferencia entre referencias y punteros es que invocar a una función que recibe referencias es mas limpio, sintácticamente, que llamar a una función que recibe punteros (y es exactamente esa diferencia sintáctica la que hace a las referencias esenciales en ciertas situaciones). Si PassAddress.cpp se modifica para utilizar referencias, se puede ver la diferencia en la llamada a la función en main():

//: C03:PassReference.cpp
#include <iostream>
using namespace std;

void f(int& r) {
  cout << "r = " << r << endl;
  cout << "&r = " << &r << endl;
  r = 5;
  cout << "r = " << r << endl;
}

int main() {
  int x = 47;
  cout << "x = " << x << endl;
  cout << "&x = " << &x << endl;
  f(x); // Looks like pass-by-value, 
        // is actually pass by reference
  cout << "x = " << x << endl;
} ///:~

Listado 3.17. C03/PassReference.cpp


En la lista de argumentos de f(), en lugar de escribir int* para pasar un puntero, se escribe int& para pasar una referencia. Dentro de f(), si dice simplemente r (lo que produciría la dirección si r fuese un puntero) se obtiene el valor en la variable que r está referenciando. Si se asigna a r, en realidad se está asignado a la variable a la que que r referencia. De hecho, la única manera de obtener la dirección que contiene r es con el operador &.

En main(), se puede ver el efecto clave de las referencias en la sintaxis de la llamada a f(), que es simplemente f(x). Aunque eso parece un paso-por-valor ordinario, el efecto de la referencia es que en realidad toma la dirección y la pasa, en lugar de hacer una copia del valor. La salida es:

x = 47
&x = 0065FE00
r = 47
&r = 0065FE00
r = 5
x = 5

De manera que se puede ver que un paso-por-referencia permite a una función modificar el objeto externo, al igual que al pasar un puntero (también se puede observar que la referencia esconde el hecho de que se está pasando una dirección; esto se verá más adelante en el libro). Gracias a esta pequeña introducción se puede asumir que las referencias son sólo un modo sintácticamente distinto (a veces referido como «azúcar sintáctico») para conseguir lo mismo que los punteros: permitir a las funciones cambiar los objetos externos.