C ++: Paso del argumento “pasado por referencia”

Entiendo que, como con cualquier otra variable, el tipo de parámetro determina la interacción entre el parámetro y su argumento. Mi pregunta es: ¿cuál es el razonamiento detrás de por qué harías referencia a un parámetro frente a por qué no lo harías? ¿Por qué algunos parámetros de funciones son de referencia y otros no? ¿Tiene problemas para entender las ventajas de hacerlo, podría alguien explicar?

La capacidad de pasar por referencia existe por dos razones:

  1. Para modificar el valor de los argumentos de la función
  2. Para evitar hacer copias de un objeto por motivos de rendimiento

Ejemplo para modificar el argumento

void get5and6(int *f, int *s) // using pointers { *f = 5; *s = 6; } 

esto se puede usar como:

 int f = 0, s = 0; get5and6(&f,&s); // f & s will now be 5 & 6 

O

 void get5and6(int &f, int &s) // using references { f = 5; s = 6; } 

esto se puede usar como:

 int f = 0, s = 0; get5and6(f,s); // f & s will now be 5 & 6 

Cuando pasamos por referencia, pasamos la dirección de la variable. Pasar por referencia es similar a pasar un puntero; solo la dirección se pasa en ambos casos.

Por ejemplo:

 void SaveGame(GameState& gameState) { gameState.update(); gameState.saveToFile("save.sav"); } GameState gs; SaveGame(gs) 

O

 void SaveGame(GameState* gameState) { gameState->update(); gameState->saveToFile("save.sav"); } GameState gs; SaveGame(&gs); 


Como solo se pasa la dirección, no es necesario copiar el valor de la variable (que podría ser realmente grande para objetos grandes). Por lo tanto, pasar por referencia mejora el rendimiento, especialmente cuando:

  1. El objeto pasado a la función es enorme (usaría la variante del puntero aquí para que la persona que llama sabe que la función puede modificar el valor de la variable)
  2. La función podría ser llamada muchas veces (por ejemplo, en un bucle)

Además, lea sobre las referencias de const . Cuando se usa, el argumento no se puede modificar en la función.

Este artículo me ayudó mucho.

Por favor, olvídate de los indicadores por ahora. Y toma esto con un grano de sal.

Una referencia es el objeto. Cuando pasa por referencia, pasa el objeto.

Cuando pasa por valor, pasa una copia del objeto; otro objeto Puede tener el mismo estado , pero es una instancia diferente ; Un clon.

Por lo tanto, puede tener sentido pasar por referencia si usted:

  • necesita modificar el objeto dentro de la función
  • no necesita (o desea) modificar el objeto, pero desea evitar copiarlo solo para pasarlo a una función. Esta sería una referencia const .

Y puede tener sentido pasar por valor si usted:

  • quiero comenzar desde un gemelo idéntico , y dejar intacto al gemelo original
  • no me importa el costo de copiar el objeto (por ejemplo, no pasaría un int por referencia a menos que quisiera modificarlo).

Aquí, mira este código:

 #include struct Foo { Foo() { } void describe() const { std::cout< <"Foo at address "< 

Y comstackrlo así: g++ example.cpp

Ejecútelo: ./a.out

Y verifique la salida (las direcciones reales pueden ser diferentes en su computadora, pero el punto permanecerá):

 Original Foo Foo at address 0x7fff65f77a0f called byreference Foo at address 0x7fff65f77a0f called byvalue Foo at address 0x7fff65f779f0 

Observe cómo la dirección de called byreference es la misma que la dirección Original Foo (ambos son 0x7fff65f77a0f ). Y observe cómo la dirección de called byvalue es diferente (es 0x7fff65f779f0 ).

Llévelo a un nivel superior. Modifique el código para que se vea de la siguiente manera:

 #include #include // for sleeping struct Foo { Foo() { } Foo(const Foo&) { sleep(10); // assume that building from a copy takes TEN seconds! } void describe() const { std::cout< <"Foo at address "< 

Compile de la misma manera, y observe la salida (los comentarios no están en la salida, se incluyen para mayor claridad):

 Original Foo Foo at address 0x7fff64d64a0e called byreference Foo at address 0x7fff64d64a0e # this point is reached "immediately" called byvalue # this point is reached TEN SECONDS later Foo at address 0x7fff64d64a0f 

Por lo tanto, el código pretende exagerar el costo de una copia: cuando llamó por referencia, este costo NO se incurrió. Cuando llamabas por valor, tenías que esperar diez segundos.

Nota: mi código fue comstackdo en OS X 10.7.4 usando GCC 4.8.1. Si está en Windows, es posible que necesite algo diferente de unitsd.h para que funcione la llamada de unitsd.h .

Tal vez esto ayude.

Ventajas de usar el pase por referencia: no es necesario que cree una copia de los datos que está pasando solo el puntero en la memoria. (El gran rendimiento gana si piensas que tienes un objeto masivo que pasaste). Puede “devolver” valores múltiples Sé que algunas funciones en c / c ++ devuelven un número y uno de los parámetros es un puntero a los datos que se manipulan.

Contras de usar el pase por referencia: debe tener cuidado al modificar los datos transmitidos, ya que podría causar efectos secundarios que puede o no desear.