Ver Mensaje Individual
  #6 (permalink)  
Antiguo 30/09/2014, 19:47
Avatar de vangodp
vangodp
 
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 11 años, 1 mes
Puntos: 38
Pasar estructura por referencia, puntero y por valor en C++

Doy por echo que algo de punteros ya sabes.
para c++ y solo c++, cuando se refiere a referencia no es lo mismo que puntero.

Primero debo explicar que es referencia y que es puntero.

una referencia se crea asi:
int &ref = variable;

y un puntero se crea asi:
int *ptr = &variable;

Pero el puntero tambien lo puedes crear asi:
int *ptr = NULL;
ptr = &variable;


Sin embargo la referencia no puedes hacer:
int &ref = NULL;
ref = variable;


...o:
int &ref = NULL;
ref = &variable;

Nada de eso... solo puedes hacer lo primero:
int &ref = variable;

Tener claro 2 cosas. un puntero no es mas que una variable ¿ok? Es una variable que apunta a una dirección de memoria. Si es variable podemos cambiar a la dirección a la que apunta ¿Correcto?
Sin embargo las referencia no puedes cambiar a lo que apunta. Se define y se inicializa al mismo tiempo, o sea:
1º un puntero es una variable que apunta a otra variable.
2º una referencia es parecido a un puntero pero con la diferencia que no puedes cambiar lo que apunta, y por ese motivo se debe definir a lo que apunta a la hora de criarlo.

Esos son los 2 conceptos que debes acordarte siempre para que no te duela la cabeza ;).
Ahora veamos un par de ejemplos de como pasar una estructura con punteros y como pasarla con referencia.

1ºPuntero.
Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. //esta esra nuestra estructura de prueba. Simplemente va guardar una frase o palabra que la distinga de las demas ;)
  5. struct foo{
  6.     string frase;
  7. };
  8.  
  9. //esta es la funcion que usaremos para pasar la estructura por punteros
  10. void bar(struct foo *foobar ){
  11.     //recibimos un puntero que apunta donde esta la estructura en memoria
  12.     cout << "Recibimos en la funcion bar: "<< foobar->frase << endl << endl; // observacion: si paso la estructura por puntero accedo a su variable miembro interna con el operador -> en ves de punto(lo entenderas cuando veas el puntero this de momento no te preucupes entenderlo si aun no llegaste en THIS POINTER).
  13.     //ahora vamos a modificar lo que tiene para provar que estoy modificando el original y no una copia como lo que acontece cuando pasamos una estructura por valor
  14.     foobar->frase = "\"Dale like y suscribete a mi canal XDD\"";
  15.     //al final de todos los ejemplos te dejo un ejemplo al que demostro que si pasas por valor una estructura, estas pasando una copia.
  16.     cout << "La estructura ahora contiene: "<< foobar->frase << endl;
  17.     cout << "Pulse enter para salir de la funcion bar()";
  18.     cin.ignore();
  19. }
  20.  
  21.  
  22. int main () {
  23.     //creamos un objeto de la estructura foo y lo llamamos f
  24.     struct foo f;
  25.    
  26.     //ponemos algo en esa estructura para que la distinga de las demas
  27.     f.frase = "Hola mundo";
  28.    
  29.     //pasamos la estructura a la funcion
  30.     bar(&f);
  31.    
  32.     //de vuelta a main
  33.     cout << "\nYa estamos de vuelta en main! Pulse enter para seguir" << endl;
  34.     cin.ignore();
  35.    
  36.     //Si la frase de la estructura f ha sido modificada realmente imprimira lo que la hemos metido en la funcion bar(), si no es asi imprimirá "hola mundo"
  37.     cout << f.frase << endl;
  38.    
  39.     //si a esta altura ha imprimido "Hola mundo" nuestro trabajo ha salido malo pero si imprimio "Dale like y suscribete a mi canal XDD" pues eso XD "Dale like y suscribete a mi canal XDD"
  40.    
  41.     return 0;
  42. }

2º Referencia
Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. //esta esra nuestra estructura de prueba. Simplemente va guardar una frase o palabra que la distinga de las demas ;)
  5. struct foo{
  6.     string frase;
  7. };
  8.  
  9. //esta es la funcion que usaremos para pasar la estructura por referencia
  10. void bar(struct foo &foobar ){ //notese que aqui uso el operador & a la hora de declarar y no * como en los punteros. foobar esta "vinculado" con la estructura f de main y no se puede reasignar otra estructura como en los punteros
  11.    
  12.     //recibimos una referencia a la direccion de la estructura(los cambios se hacen en la misma estructura como los punteros)
  13.     cout << "Recibimos en la funcion bar: "<< foobar.frase << endl << endl; // observacion: no uso -> sino punto normal ;)
  14.    
  15.     //ahora vamos a modificar lo que tiene para provar que estoy modificando el original y no una copia como lo que acontece cuando pasamos una estructura por valor
  16.     foobar.frase = "\"Dale like y suscribete a mi canal XDD\"";
  17.    
  18.     //al final de todos los ejemplos te dejo un ejemplo al que demostro que si pasas por valor una estructura, estas pasando una copia.
  19.     cout << "La estructura ahora contiene: "<< foobar.frase << endl;
  20.    
  21.     cout << "Pulse enter para salir de la funcion bar()";
  22.     cin.ignore();
  23. }
  24.  
  25.  
  26. int main () {
  27.     //creamos un objeto de la estructura foo y lo llamamos f
  28.     struct foo f;
  29.    
  30.     //ponemos algo en esa estructura para que la distinga de las demas
  31.     f.frase = "Hola mundo";
  32.    
  33.     //pasamos la estructura a la funcion (por referencia) NOTA: no debo poner el operador & delante como hago con punteros, la referencia ya espera la direccion asi que no tengo por que poner & ;)
  34.     bar(f);
  35.    
  36.     //de vuelta a main
  37.     cout << "\nYa estamos de vuelta en main! Pulse enter para seguir" << endl;
  38.     cin.ignore();
  39.    
  40.     //Si la frase de la estructura f ha sido modificada realmente imprimira lo que la hemos metido en la funcion bar(), si no es asi imprimirá "hola mundo"
  41.     cout << f.frase << endl;
  42.    
  43.     //si a esta altura ha imprimido "Hola mundo" nuestro trabajo ha salido malo, pero si imprimio "Dale like y suscribete a mi canal XDD" pues eso XD "Dale like y suscribete a mi canal XDD"
  44.    
  45.     return 0;
  46. }

3º paso por valor
"paso de copias" Nada recomendable para estructuras grandes que te pueden llenar rápidamente la memoria.

Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. //esta esra nuestra estructura de prueba. Simplemente va guardar una frase o palabra que la distinga de las demas ;)
  5. struct foo{
  6.     string frase;
  7. };
  8.  
  9. //esta es la funcion que usaremos para pasar la estructura por valor
  10. void bar(struct foo foobar){
  11.    
  12.     //recibimos una copia, realmente tiene lo mismo que la estructura f de main pero no es ella
  13.     cout << "Recibimos en la funcion bar: "<< foobar.frase << endl << endl; // observacion: no uso -> sino punto normal ;)
  14.    
  15.     //ahora vamos a modificar la copia no la autentica, ya lo demostrare
  16.     foobar.frase = "\"Dale like y suscribete a mi canal XDD\"";
  17.    
  18.     cout << "La estructura de copia contiene: "<< foobar.frase << endl;
  19.    
  20.     cout << "Pulse enter para salir de la funcion bar(). \nEso no producira ningun cambio en la estructura original.";
  21.     cin.ignore();
  22.     //cuando salgamos de la funcion bar la estructura de copia se destruira y la autentica seguirá intacta.
  23. }
  24.  
  25.  
  26. int main () {
  27.     //creamos un objeto de la estructura foo y lo llamamos f
  28.     struct foo f;
  29.    
  30.     //ponemos algo en esa estructura para que la distinga de las demas
  31.     f.frase = "Hola mundo";
  32.    
  33.     //pasamos la estructura a la funcion (por valor) NOTA: lo que va recibir la funcion foo es una copia de la autentica funcion, los cambios realmente no se van a producir en la autentica sino en la copia.
  34.     bar(f);
  35.    
  36.     //de vuelta a main
  37.     cout << "\nYa estamos de vuelta en main! Pulse enter para seguir" << endl;
  38.     cin.ignore();
  39.    
  40.     //Si la frase de la estructura f ha sido modificada realmente imprimira lo que la hemos metido en la funcion bar(), si no es asi imprimirá "hola mundo"
  41.     cout << f.frase << endl;
  42.    
  43.     //si a esta altura ha imprimido "Hola mundo" es que los cambios en la funcion bar no surten efectos en la estructura original. Si imprime"Dale like y suscribete a mi canal XDD" es que la estariamos modificando la original.
  44.    
  45.     return 0;
  46. }

Por ultimo dejo un ejemplo de como lo guardamos la estructura de copia en la original.
Código C++:
Ver original
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. //esta esra nuestra estructura de prueba. Simplemente va guardar una frase o palabra que la distinga de las demas ;)
  5. struct foo{
  6.     string frase;
  7. };
  8.  
  9. //notese que el tipo de retorno de la funcion es el tipo de la funcion foo:
  10. foo bar(struct foo foobar){  //retornamos una estructura tipo foo ;)
  11.     foobar.frase = "\"Dale like y suscribete a mi canal XDD\""; //modificamos la copia
  12.     return foobar; //retornamos la copia. Debemos guardarla sino se perdera al salir de la funcion bar() y no tendria sentido la funcion en dicho caso
  13. }
  14.  
  15.  
  16. int main () {
  17.     struct foo f;
  18.    
  19.     f.frase = "Hola mundo";
  20.    
  21.     f = bar(f); //guardamos la estructura que retorna la funcion bar
  22.    
  23.     cout << "\nYa estamos de vuelta en main! Pulse enter para seguir" << endl;
  24.     cin.ignore();
  25.    
  26.     //Como ahora guardamos lo que nos retorno la funcion bar imprimira lo que habia alli que es "Dale like y suscribete a mi canal XDD" y no "Hola mundo"
  27.     cout << f.frase << endl;
  28.    
  29.     return 0;
  30. }

Bueno... eso es todo.
Aprenda todo sobre punteros, que no te quede dudas.
Si quieres llegar a ser un buen programador, los punteros son esenciales. Y es por ese motivo que todos se tiran a java a bandadas jajaja ya que según tengo entendido java no necesitas trabajar con ellos aun que si me parece que también se puede o yo que se jaja.

continua abajo jaja...