2011-10-02 22 views
11

¿Existe una necesidad rendimiento -wise para línea funciones pasan a sus argumentos por la referencia const comoInline Argumentos función de propagación

foo(const T & a, const T &b) 

en comparación con el valor por

foo(T a, T b) 

si No cambio los valores de ayb en la función? ¿El cambio C++ 11 recomienda algo específico aquí?

+2

Un valor es un valor y una referencia es una referencia.Pasar una referencia constante cuando en su lugar se está pasando un valor es un error que puede afectar negativamente. Consulte http://stackoverflow.com/questions/4705593/int-vs-const-int/4705871#4705871 – 6502

+0

@ 6502: ese es un gran ejemplo de un caso en el que el uso de una referencia complica la lógica ('v.push_back (v [0]) 'es legal, porque la biblioteca estándar debe incluir esa lógica extra). –

+0

@BenVoigt: Es bueno ver que esta solicitud se ha agregado a la norma. ¿Dónde está declarado? – 6502

Respuesta

11

Pasar por valor solo puede elide la llamada copy-constructor si el argumento es temporal.

Pasar los tipos primitivos por const reference no tendrá costo cuando la función esté en línea. Pero pasar un lvalue complejo por valor impondrá una llamada de constructor de copia potencialmente costosa. Por lo tanto, prefiero pasar por referencia constante (si el aliasing no es un problema).

+0

Además de los problemas de aliasing hay problemas de por vida. – 6502

+0

@ 6502: en valores devueltos, definitivamente. Para los parámetros, pueden ocurrir problemas de por vida, pero son muy raros. Y los consideraría un subconjunto de problemas de aliasing de todos modos. –

+0

@BenVoigt 'Pasar los tipos primitivos por referencia no tendrá costo alguno cuando la función esté en línea. ¿Quiere decir que" no tendrá ningún beneficio en términos de costo "? ¿Puedes confirmar si hay algo que ganar pasando un 'const int &' o un 'const int' cuando la función está en línea? – Antonio

1

Pase por referencia es más rápido que por valor según el tipo de datos.
Sin embargo, para las funciones en línea el cuerpo de la función (y por lo tanto todas las referencias/valores pasados) se agregan a la línea de código que se usan, por lo que técnicamente no se pasan variables, solo más líneas de código en la misma área .

referencia http://www.cprogramming.com/tutorial/lesson13.html

También hay una respuesta muy útil bajo la pregunta should-i-take-arguments-to-inline-functions-by-reference-or-value

  • ejemplo puede haber sido engañoso, retirado -
+1

Esto es completamente especulativo. – pmr

+1

Pasar por referencia es más rápido que por valor ** según el tipo **. Además, el código que usa una referencia tiene requisitos adicionales (para manejar correctamente el aliasing) y puede requerir un direccionamiento adicional innecesario para los tipos nativos pasados ​​por valor. – 6502

+0

Disculpas, obtuve el puntero de pase combinado con el valor por alguna extraña razón, tienes razón, es solo más rápido para algunos tipos de datos. También te señalo http://stackoverflow.com/questions/722257/should-i-take-arguments-to-inline-functions-by-reference-or-value que admite mi punto – Serdalis

4

En teoría los que no tienen referencia pueden ser copiados en memoria ya que existe la posibilidad de que su función en línea pueda modificarlos (incluso si no lo hace).

En muchos casos, el compilador es lo suficientemente inteligente como para elegir ese tipo de cosas, pero dependerá del compilador y de la configuración de optimización. Además, si su función llama a cualquier función miembro no const en las variables de clase, entonces su compilador tendrá que ser lo suficientemente inteligente como para comprobar si también están modificando algo.

Al usar una referencia constante, básicamente puede darle una indicación bastante clara.

EDITAR: Acabo de ver el código de máquina para un simple test program compilado con GCC 4.6 en ddd. El código generado parecía idéntico, por lo que parece estar optimizado. Sin embargo, sigue siendo una buena práctica para otros compiladores y, si nada más da una indicación clara de la intención del código. También es posible que existan situaciones más complejas que el compilador no puede optimizar.

También el llvm online dissembler demo muestra idéntico código de bits generado allí también. Si desactiva la optimización, es un poco más larga sin la referencia constante.
* 1964 bytes - Sin referencia de referencias (y ninguna otra depende de las funciones/parámetros)
* 1960 bytes - Simplemente no referencia const pero otras consts.
* 1856 bytes - Con consts y referencia constante.

+1

Si la función en línea pasa a y b a otra función, puede que no sea posible optimizar la copia. Por ejemplo, si la función en línea llama a la función no en línea 'bar (a)' el compilador debe copiar porque la barra puede hacer 'if (& a == & special) ...' y la persona que llama original puede haber pasado 'special'. –

+0

Vuelve a intentarlo, con un tipo que no sea POD. –

+0

No importa para el optimizador si una función miembro se declara 'const' o no.La corrección de const es invisible para el optimizador y es algo que ha sido diseñado solo para ayudar a los programadores (dando errores de tiempo de compilación si viola las declaraciones const), no el optimizador. – 6502