Las referencias
Una referencia es otra forma de acceder a un dato, una especie de alias. Cualquier operacion sobre una referencia afectara a ese dato al que hace referencia. Veamos un ejemplo simple:
/**
* Referencias.cpp
* Programa que muestra el uso de referencias
*
* Pello Xabier Altadill Izura
*
* Compilado: g++ Referencias.cpp -o Referencias
*/

#include <iostream.h>

int main() {

	// Definimos un dato y su referencia
	int numero;
	int &referenciaNumero = numero; // Ahi se crea la referencia

	cout << "Vamos a ver que pasa si le asignamos un dato: " << endl;

	numero = 31337;

	// Los dos mostraran el mismo valor
	cout << "Valor de numero: " << numero << endl;
	cout << "Valor de referenciaNumero: " << referenciaNumero << endl;

	// y a donde apuntan? AL MISMO SITIO
	cout << "Posicion de numero: " << &numero << endl;
	cout << "Posicion de referenciaNumero: " << &referenciaNumero << endl;

	cout << "Programa terminado
" << endl;

        return 0;
}
Con los objetos se pueden hacer referencias igualmente:
Objeto miObjeto;
Objeto &refObjeto = miObjeto;
Referencias y funciones
Vamos a ver distintas formas de pasar referencias a una funcion.
Como en c, podemos pasar parametros por referencia y hacer que esos parametros contengan resultados de una funcion.
/**
* ReferenciaFunciones.cpp
* Programa que muestra el uso de referencias en las funciones
*
* Pello Xabier Altadill Izura
*
* Compilado: g++ ReferenciaFunciones.cpp -o ReferenciaFunciones
*/

#include <iostream.h>

// 1º funcion que intercambia dos valores
void exchange (int *refa, int *refb);

// 2º funcion -sobrecargada- que intercambia dos valores
void exchange (int &refa, int &refb);

int main() {

	// Definimos un dato y su referencia
	int a, b;

	cout << "Asignamos valores: " << endl;

	a = 45;
    b = 21;

	cout << "Valores: a=" << a << " b=" << b << endl;
	cout << "Hacemos intercambio con exchange(int *refa, int *refb): " << endl;
	exchange(&a, &b);  // Con esta llamada invocamos la primera funcion!!
	cout << "Valores: a=" << a << " b=" << b << endl;


	cout << "Hacemos intercambio con exchange(int &refa, int &refb): " << endl;
	exchange(a, b);  // Con esta llamada invocamos la segunda funcion!!
	cout << "Valores: a=" << a << " b=" << b << endl;

	cout << "Programa terminado
" << endl;

        return 0;
}

// 1º funcion que intercambia dos valores
void exchange (int *refa, int *refb) {
    int tmp;
    tmp = *refa;
    *refa = *refb;
    *refa = tmp;
}

// 2º funcion -sobrecargada- que intercambia dos valores
void exchange (int &refa, int &refb) {
    int tmp;
    tmp = refa;
    refa = refb;
    refa = tmp;
}

Pasando clases por referencia
/**
* Gremlin.hpp
*
* Clase que representa el objeto Gremlin.
* Observese el 3º metodo constructor
* Pello Xabier Altadill Izura
*
*/

#include <iostream.h>

class Gremlin {
public:
	Gremlin();
	Gremlin(char *nmb,int ed, int p);
	Gremlin(Gremlin&); // atencion a este constructor
	~Gremlin();
	void correr();
	void dormir();
	void morder();

	int peso;

private:
	char *nombre;
	int edad;
};
Y su implementacion:
/**
* Gremlin.cpp
*
* Clase que implementa el objeto Gremlin.
* Pello Xabier Altadill Izura
*
*/

#include "Gremlin.hpp"

Gremlin::Gremlin() {
 peso = 1;
 cout << "Gremlin creado." << endl;
}

Gremlin::Gremlin (char *nmb,int ed, int p) {
    nombre = nmb;
    edad = ed;
    peso = p;
}

Gremlin::~Gremlin() {
 cout << "Aaaargh!
Gremlin destruido." << endl;
}

// El gremlin corre
void correr() {
 cout << "Jaja grrrr!! jajaja!" << endl;
}

// El gremlin duerme
void dormir() {
 cout << "zzzZZZZzzzzz" << endl;
}

// El gremlin muerde
void morder() {
 cout << "roaar ñam ñam" << endl;
}

// Definimos esta funcion aparte de la clase
// Con ella el gremlin come y aumenta su atributo peso.
void comer (Gremlin *g) {
    // Invocamos la mordedura para que coma
    g->morder();
    // Le aumentamos 3 unidades por comer
    g->peso += 3;
}

// Funcion main
int main () {
    cout << "Iniciando programa. " << endl;

    // Definimos un gremlin
    Gremlin tbautista;
    // y lo movemos por la ciudad
    tbautista.correr();
    tbautista.morder();

    // Mostramos su peso
    cout << "El gremlin pesa: " << tbautista.peso << endl;

    // Le hacemos comer:
    comer(&tbautista);

    // Mostramos su peso otra vez
    cout << "El gremlin pesa ahora: " << tbautista.peso << endl;

    cout << "Finalizando programa
 " << endl;
    return 0;
}
La ventaja que logramos al pasar parametros por referencia es que ahorramos espacio en memoria ya que sino en cada llamada a una funcion se hacen copias de los parametros. Esto tambien tiene una desventaja: si le pasamos a una funcion el ORIGINAL de un objeto (con una referencia) en lugar de una copia corremos el riesgo de que la funciona haga trizas nuestro objeto y perder el "original" (supongamos que la funcion esta hecha por terceros y no sabemos lo que hace).
Que se puede hacer para salvaguardar nuestros objetos?
Punteros constantes
Esta es la solucion: pasar punteros constantes. Eso hara que la funcion solo tenga permiso para invocar los metodos constantes de la clase. SE cambia un poco la clase gremlin para mostrar esto.
/**
* Gremlin2.hpp
*
* Clase que representa el objeto Gremlin.
* Con un metodo definido como const!!
* Pello Xabier Altadill Izura
*
*/

#include <iostream.h>

class Gremlin {
public:
	Gremlin();
	Gremlin(char *nmb,int ed, int p);
	Gremlin(Gremlin&); // atencion a este constructor
	~Gremlin();
	void correr();
	void dormir();
	void morder();
	// Definimos una funcion constante
	char * getNombre() const;
	int peso;

private:
	char *nombre;
	int edad;
};
Y vemos la implementacion en la que simplemente se puede observar como se protege el objeto en la funcion comer() gracias al uso de punteros constantes.
/**
* Gremlin2.cpp
*
* Clase que implementa el objeto Gremlin.
* Pello Xabier Altadill Izura
*
*/

#include "Gremlin2.hpp"

Gremlin::Gremlin() {
 peso = 1;
 cout << "Gremlin creado." << endl;
}

Gremlin::Gremlin (char *nmb,int ed, int p) {
    nombre = nmb;
    edad = ed;
    peso = p;
}

Gremlin::~Gremlin() {
 cout << "Aaaargh!
Gremlin destruido." << endl;
}

// El gremlin corre
void correr() {
 cout << "Jaja grrrr!! jajaja!" << endl;
}

// El gremlin duerme
void dormir() {
 cout << "zzzZZZZzzzzz" << endl;
}

// El gremlin muerde
void morder() {
 cout << "roaar ñam ñam" << endl;
}

// FUNCION CONST!!!
// Devuelve el nombre del gremlin
char * getNombre() const {
    return nombre;
}

// Definimos esta funcion aparte de la clase
// Con ella el gremlin come y aumenta su atributo peso.
void comer (const Gremlin const *g) {
    // Invocamos la mordedura para que coma??
//    g->morder(); ERROR no podemos invocar una funcion NO CONSTANTE!!!
// en cambio si podemos invocar getNombre
    cout << "Nombre" << g->getNombre() << endl;
}

// Funcion main
int main () {
    cout << "Iniciando programa. " << endl;

    // Definimos un gremlin
    Gremlin tbautista;
    // y lo movemos por la ciudad
    tbautista.correr();
    tbautista.morder();

    // Mostramos su peso
    cout << "El gremlin pesa: " << tbautista.peso << endl;

    // Le hacemos comer:
    comer(&tbautista);

    // Mostramos su peso otra vez
    cout << "El gremlin pesa ahora: " << tbautista.peso << endl;

    cout << "Finalizando programa
 " << endl;
    return 0;
}