11/16/2005

Paso por referencia en C++

Paso por referencia o por valor.

Como vimos las funciones por lo general reciben parámetros, éstos hasta el momento fueron pasados a la función mediante el "paso por valor" que consiste en hacer un copia del argumento, para que la función trabaje con la copia y no con el argumento original.

Esto significa que si la función modificara el valor, el original no se alteraría ya que estamos manejando una copia. Esto resulta bastante útil para asegurarnos de que la función no modifique nuestros argumentos de manera accidental.

Pero surgen dos problemas:

  1. Podríamos querer modificar el argumento original y no una copia.
  2. Con mucha cantidad de variables (o estructuras como veremos) el paso por valor (copiando) puede resultar un gasto excesivo de memoria.

Para resolver estos problemas contamos con las referencias y punteros, por el momento nos ocuparemos de las referencias.

Una referencia a una variable es un "alias" de la variable. Para indicarle a C++ que estamos hablando de una referencia y no una variable anteponemos al nombre el caracter ampersand (&).

Por ejemplo una referencia llamada refPresupuesto apuntando a un valor double se escribiría así:

double &refPresupuesto

Si quisieramos que una función trabaje con la variable original y no con una copia podríamos indicarle a la función que reciba el parametro como una referencia, veamos un ejemplo:

//Paso por referencia
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void elevarCuadrado (int &); //prototipo de funcion que recibe una referencia a un int
int main()
{
  int x = 0; //Declaracio e inicializacion en 0.
  cout << "Ingrese x para elevarlo al cuadrado" << endl;
  cin >> x;
  cout << "antes de elevarse es " << x <<endl;
  elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor.
  cout << "x despues de elevarse es " << x << endl;//muestra el valor modificado por la funcion
  return 0;
}
void elevarCuadrado (int &y ) //funcion que no devuelve nada (void) y recibe una referencia a un int en este caso (x)
{
  y = y*y; //La funcion no devuelve ningun valor, pero modifica el argumento original (x)
  //ya que estamos trabajando con una referencia.
}

Cuando una función se declara anteponiendo la palabra reservada void le estamos diciendo a C++ que esa función no devolvera valor alguno.

Como se comenta en el código, en la llamada de la función es importante notar que no hay manera de darse cuenta si el parametro es pasado por referencia (modificable) o si es por valor (se le envía una copia a la función).

Paso por referencia constante

Además de poder modificar el valor, aquí obtenemos la ventaja de no realizar una copia de la variable en cuestión. Sin embargo podríamos querer obtener esta ventaja (de aprovechar memoria), pero no perder la protección de la variable (que la original no pueda ser modificada por la función). Este problema se resuelve, declarando en la función una referencia constante, con la palabra reservada const.

Esto haría que se pase el argumento por valor, pero que no se permita la modificación de la variable original. Si al código anterior le agregasemos la palabra const en el prototipo y en la declaración, e intentasemos compilarlo generaríamos un error, ya que el compilador nos avisa que no se puede modificar el valor al que apunta la referencia, lo cual es muy útil para detectar errores. El código quedaría así y pueden probarlo:

//Paso por referencia constante.
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void elevarCuadrado (const int &); //prototipo de funcion que recibe una referencia a un int
int main()
{
  int x = 0; //Declaracio e inicializacion en 0.
  cout << "Ingrese x para elevarlo al cuadrado" << endl;
  cin >> x;
  cout << "antes de elevarse es " << x <<endl;
  elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor.
  cout << "x despues de elevarse es " << x << endl;
  return 0;
}
void elevarCuadrado (const int &y ) //funcion que no devuelve nada (void) y recibe una referencia a un int en este caso (x)
{
  y = y*y; // Error no se puede modificar ya que es constante.

}

Aviso del compilador:

refConstEj.cpp: In function ‘void elevarCuadrado(const int&)’:
refConstEj.cpp:19: error: assignment of read-only reference ‘y’

Ver como hacer para compilar este programa.

1 comentario:

Diego dijo...

Bueno, si yo defino la funcion en el inicio del programa con sin incluir el &, parece que no sucede nada. Lo intente y resulta igual, a que se debe, o en que se diferencia con el paso normal?????????'