¿Dónde debería preferir pasar por referencia o pasar por valor?

¿En qué circunstancias debería preferir pasar por referencia? ¿Pasa por valor?

Hay cinco casos principales en los que debe usar pass-by-reference sobre pass-by-value:

  1. Si llama a una función que necesita modificar sus argumentos, use pass-by-reference ya que es la única forma de obtener este efecto (trato el pass-by-reference y el pass-by-pointer indistintamente en este caso, aunque con el pase por puntero, a menudo tiene que comprobar explícitamente NULL).
  2. Si está llamando a una función que necesita tomar un objeto grande como parámetro, páselo por referencia constante para evitar hacer una copia innecesaria de ese objeto y obtener un gran golpe de eficiencia.
  3. Si está escribiendo un constructor de copia que por definición debe tomar una referencia, use pasar por referencia.
  4. Si está escribiendo una función que quiere operar en una clase polimórfica, use pasar por referencia o pasar por el puntero para evitar rebanar.
  5. Si está escribiendo una función que podría devolver un objeto muy grande o imposible de copiar, use pasar por referencia como una forma de usar un parámetro para almacenar el valor producido.

Hay varias consideraciones, que incluyen:

Actuación

Pasar por valor copia los datos, por lo que pasar grandes estructuras de datos por valor puede nhibernate el rendimiento. Pasar por referencia pasa solo una referencia (básicamente la dirección) a los datos. Para estructuras de datos grandes, esto puede mejorar enormemente el rendimiento. Para estructuras de datos más pequeñas (como un int), pasar por referencia puede nhibernate el rendimiento.

Modificaciones

Pasar por valor copia los datos, de modo que si el código objective modifica esa copia, no afectará al original. Pasar por referencia pasa solo la dirección de los datos, por lo que las modificaciones hechas contra esa referencia serán “visibles” para el código de llamada.

Sí.

Pase por valor para cosas como tipos nativos que son lo suficientemente pequeños como para pasarlos directamente es eficiente. De lo contrario, use pass by ( const ) reference.

La parte difícil es escribir una plantilla que podría aplicarse a cualquiera de los dos (en cuyo caso, normalmente desea utilizar el pase por referencia; la penalización potencial por pasar un objeto grande por valor es mucho peor que la penalización potencial por pasar por referencia al pasar). por valor hubiera sido preferido).

Editar: esto, por supuesto, supone una situación en la que la semántica requerida permitiría cualquiera de los dos: obviamente, si trabajas con objetos polimórficos, no hay una “preferencia” real, porque debes usar un puntero o una referencia para obtener el comportamiento correcto.

Como otros ya han respondido a su pregunta lo suficientemente bien, me gustaría agregar un punto importante:

Si la clase no tiene public constructor de copiado public , entonces no tiene opción de pasar por el valor; tienes que pasar por referencia (o puedes pasar el puntero).

El siguiente progtwig no comstackría:

 class A { public: A(){} private: A(const A&) {} }; //source of error : pass by value void f(A ) {} int main() { A a; f(a); return 0; } 

Error:

prog.cpp: en la función ‘int main ()’:
prog.cpp: 10: error: ‘A :: A (const A &)’ es privado
prog.cpp: 18: error: dentro de este contexto
prog.cpp: 18: error: inicialización del argumento 1 de ‘void f (A)’

Véalo en ideone: http://www.ideone.com/b2WLi

Pero una vez que haces que la función f pase por referencia, comstack bien: http://www.ideone.com/i6XXB

Ha marcado su pregunta con C y C ++.

Por lo tanto, le sugiero que considere utilizar pass by reference en C ++ que admita esta característica y que no considere usarlo en C, que no es compatible con esta característica.

Mientras que los punteros son referencias, “referencia” en c ++ generalmente se refiere a la práctica de etiquetar un parámetro de SomeType &.

Que nunca deberías hacer El único lugar donde es apropiado es como una syntax mágica necesaria para implementar los diversos operadores predefinidos. De otra manera:

  • Nunca debe pasar los parámetros por referencia, pase por el puntero, de lo contrario, hará que las revisiones de los códigos sean prácticamente imposibles. Pasar por referencia hace que sea imposible saber mediante el examen de una llamada qué parámetros pueden esperarse cambiar.

  • Nunca debe pasar el parámetro por referencia tampoco. De nuevo, esto significa que está realizando una meta optimización. Siempre debe simplemente pasar por valor, de lo contrario es culpable de mirar dentro de un objeto, examinar su implementación y decidir que se prefiere pasar por referencia por alguna razón.

Cualquier clase de c ++ debe implementar todos los constructores de copia y asignación y las sobrecargas necesarias para pasar por valor. De lo contrario, no ha hecho su trabajo, de abstraer al progtwigdor de los detalles de implementación de la clase.