jueves, 14 de julio de 2016

Pasar argumentos por valor, referencia o puntero

Pasar por valor un argumento

Esta es la forma en la que los argumentos se pasan por defecto en C++. Lo que hacemos cada vez es que pasamos una copia a la función del argumento, lo que significa que el valor original no será  modificado.

void birthDate(int _day, int _month, int _year);

La principal desventaja que tiene, es que para valores de tamaño considerable no es una opción económica, y más si la función se llama varias veces. En la función anterior no habría problema, aunque no es la forma óptima de hacerlo. En cambio con la función siguiente la cosa cambia:

struct userData {
    int marks[100];
};
void calcAverage(userData _dataStruct);

Cada vez que se pase por argumento la estructura, se copiará un array de tamaño 100, que si se usa muchas veces, puede llegar a ser muy lento, y puesto que los datos de la estructura no van a cambiarse, debería de poder hacerse de otra manera.

Pasar por referencia un argumento:

Centrémonos en uno de los aspectos que más luz arroja acerca de lo que significa pasar un valor por referencia. Cuando pasamos un valor por copia como en el caso anterior, la única forma de devolver un valor es utilizando el return en la función, ya que al recibir una copia, seguramente tengamos que crear un elemento del mismo tipo que la función recibe para almacenar los cambios y después devolverlos.

Pero que sucede si lo que realmente necesito es cambiar el valor de una variable, y no hacer algo con ella. No tiene mucho sentido recibir una copia, hacer cambios y luego sobreescribir dicha variable por ejemplo de esta manera:

//main.cpp

struct Alum{
    double mark;
};
double updateMarksBonus(Alum _al, double _bonus){
    double newMark = _al.mark + _bonus;
    return newMark; 
}
int main() {
    Alum al;
    al.mark= 8.54;
    al.mark = updateMarksBonus(al, 1.4);
    cout << al.mark << endl;
    return 0;
}

Esto no tiene mucho sentido cuando pasando el valor por referencia puedo cambiar el valor de la estructura directamente de la siguiente manera:

struct Alum{
    double mark;
};
//----------------------------------------------------------
void updateMarksBonusByRef(Alum& _al, double _bonus){
    _al.mark+=_bonus;
}
//----------------------------------------------------------
int main() {
    Alum al;
    al.mark= 8.54;
    updateMarksBonusByRef(al, 1.4);
    cout << al.mark << endl;
    return 0;
}

Hay que tener cuidado, la capacidad de poder cambiar el valor original puede poner en peligro nuestro programa, ya que quizás ese valor no necesita ser cambiado, para poder utilizar valores pasados por referencia y asegurarnos de que ese valor está protegido y no va a ser cambiado, utilizaremos const references, que no es más que pasar el valor a la función y declara que ese valor que se pasa será constante:

void foo(const int& _x);

Pasar por dirección un argumento

En lugar de pasar una copia, o una referencia, pasamos un puntero. Cuando queremos acceder a grandes datos tipo arrays y queremos hacer consultas o incluso cambiar parámetros podemos utilizar esta forma de pasar valores:

void updateArray(int* _arrayPtr, int _size);

Esto es todo.

No hay comentarios:

Publicar un comentario