cuando lo usas en los parámetros, especificas que dicha variable se pasará por REFERENCIA en vez de hacerse una copia de la misma y por tanto, podrá ser modificada en la función.
void incrementar (int & valor){
valor++;
}
si hacemos:
int n=4;
incrementar(n);
n ahora vale 5. En cambio, sin el & en el parámetro de la funcion, n no se modificaría fuera del rango de la misma, sino que se modificaría una copia de n, destruída al terminar la funcion.
Cuando va delante del nombre de una función, es que la función devuelve una referencia. Se utiliza sobretodo para encadenar operadores, ejemplo:
int i,j,k;
k=j=i=1;
Esto lo puedes hacer, porque el operador = devuelve una referencia a si mismo, de forma que consigues el valor de 1 en base a la i para j, y el valor de 1 en k por el valor de j (que a su vez, como ya he dicho, se consigue con la referencia de 1 por la i).
Sobretodo se utiliza para sobrecargar operadores de clases, te pongo un ejemplo:
distancia& operator=(const distancia &assign){
dist=assign.dist;
desti=assign.desti;
return *this;
};
y esto, es lo que me permite encadenar asignaciones para mi clase "distancia"