2008-10-01 26 views

Respuesta

37

La función se coloca en el código, en lugar de ser llamado, similar al uso de macros (conceptualmente)

Esto puede mejorar la velocidad (sin llamada de función), pero causa código hinchazón (si la función se utiliza 100 veces , ahora tiene 100 copias)

Debe tener en cuenta que esto no obliga al compilador a realizar la función en línea, y lo ignorará si considera que es una mala idea. Del mismo modo, el compilador puede decidir hacer las funciones normales en línea para usted.

Esto también le permite colocar toda la función en un archivo de encabezado, en lugar de implementarlo en un archivo cpp (que de todos modos no puede, ya que se obtiene un externo no resuelto si se declaró en línea, a menos que solo el archivo cpp lo usó).

+1

Sí, y es un punto clave es que los compiladores modernos en línea de forma automática, y usar una palabra clave 'en línea' es solo una sugerencia para el compilador. Los compiladores modernos generalmente saben lo que están haciendo y eligen correctamente alinearse o no, independientemente de las palabras clave "en línea". Pero sigue siendo un concepto útil. – Jamie

+5

NOTA: inline does _not_ significa que la función estará en línea. Es posible que esté en línea, eso depende del compilador. Sin embargo, en un nivel de lenguaje/semántica, en línea significa que una función se puede definir en más de un módulo sin un error de tiempo de enlace. (las definiciones aún deben coincidir) – Aaron

+4

"Debe tener en cuenta que esto no obliga al compilador a hacer la función en línea" –

2

El cuerpo de la función se inserta literalmente dentro de la función de llamada. Por lo tanto, si tiene varias llamadas a esta función, obtendrá múltiples copias del código. El beneficio es que obtiene una ejecución más rápida.

Por lo general, las funciones muy cortas están en línea, cuando la copia del cuerpo de la función no sería mucho mayor que el código de prólogo/epílogo habitual generado para la llamada a función normal.

Usted puede leer más en el artículo de MSDN sobre inline - http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx

0

De manera informal, significa que los compiladores se les permite injertar el contenido de la función de llamada en el sitio, por lo que no hay ninguna llamada a la función. Si su función tiene grandes instrucciones de control (por ejemplo, if, switch, etc.), y las condiciones pueden evaluarse en tiempo de compilación en el sitio de llamadas (por ejemplo, valores constantes utilizados en el sitio de llamadas), su código termina mucho más pequeño (las ramas no utilizadas se dejan caer).

Más formalmente, las funciones en línea también tienen vínculos diferentes. Dejaré que los expertos en C++ hablen sobre ese aspecto.

1

Las funciones en línea alteran el perfil de rendimiento de su aplicación generando instrucciones que se colocan en el segmento de código de su aplicación. Si una función está en línea es a discreción de su compilador. En mi experiencia, la mayoría de los compiladores modernos son buenos para determinar cuándo cumplir con la solicitud de un usuario de estar en línea.

En muchos casos, la incorporación de una función mejorará su rendimiento. Hay una sobrecarga inherente a las llamadas de función. Hay razones, sin embargo, ¿por qué inlining una función podría ser negativo:

  • El aumento del tamaño del ejecutable binario mediante la duplicación de código podría conducir a la basura de disco, ralentizando su aplicación hacia abajo.
  • El código de alineación podría contribuir a fallas en la memoria caché o posiblemente contribuir a los hits de la memoria caché según su arquitectura.

El C++ FAQ hace un buen trabajo de explicar las complejidades de la palabra clave: http://www.parashift.com/c++-faq-lite/inline-functions.html#faq-9.3

+0

Las preguntas frecuentes ya están aquí: https://isocpp.org/wiki/faq/inline-functions – GetFree

0

Llamar a una función impone una cierta penalización en el rendimiento de la CPU más de sólo tener un flujo lineal de instrucciones. Los registros de la CPU deben escribirse en otra ubicación, etc. Obviamente, los beneficios de tener funciones generalmente superan la penalización de rendimiento.Pero, donde el rendimiento será un problema, por ejemplo, la legendaria función de "bucle interno" o algún otro cuello de botella, el compilador puede insertar el código de máquina para la función en el flujo principal de ejecución en lugar de pasar por el impuesto de la CPU para llamar a una función .

+1

Tiene toda la razón, plegar bucles internos y deshacerse de los saltos lejanos provoca la disminución de los posibles ciclos perdidos de la CPU debido a fallas en la memoria caché por lo tanto aumentando rendimiento desde un lado, pero aumenta la huella de caché desde el otro lado. Es por eso que es importante equilibrar estas compensaciones. – Josef

19

Así como la otra (perfectamente correcta) Respuestas a preguntas sobre las implicaciones de rendimiento de inline, en C++ también se debe tener en cuenta esto le permite poner con seguridad una función en un encabezado:

// my_thing.h 
inline int do_my_thing(int a, int b) { return a + b; } 

// use_my_thing.cpp 
#include "my_thing.h" 
... 
    set_do_thing(&do_my_thing); 

// use_my_thing_again.cpp 
... 
    set_other_do_thing(&do_my_thing); 

Esto se debe a la el compilador solo incluye el cuerpo real de la función en el primer archivo objeto que necesita una función invocable regular para ser compilada (normalmente porque se tomó su dirección, como mostré arriba).

Sin la palabra clave inline, la mayoría de los compiladores daría un error acerca de definición múltiple, por ejemplo, para MSVC:

use_my_thing_again.obj : error LNK2005: "int __cdecl do_my_thing(int,int)" ([email protected]@[email protected]) already defined in use_my_thing.obj 
<...>\Scratch.exe : fatal error LNK1169: one or more multiply defined symbols found 
0

Una función que marcar como no está permitido en línea para ser inline por el compilador. No hay garantía de que el compilador lo haga. El compilador usa semántica compleja en el dispositivo cuando lo hace o no.

Cuando el compilador decide que una función debe estar en línea, la llamada a la función, en el código de la persona que llama, se reemplaza por el código de la llamada. Esto significa que guarda las operaciones de la pila, la misma llamada y mejora la ubicación de la memoria caché del código. A veces eso puede conducir a grandes ganancias de rendimiento. Especialmente en funciones de acceso a datos de 1 línea, como los accesos utilizados en código orientado a objetos.

El costo es que generalmente dará como resultado un código más grande, lo que podría perjudicar el rendimiento. Esta es la razón por la que establecer una función en línea es solo una "bandera verde" para el compilador, que no necesita seguir. El compilador intentará hacer lo mejor.

Como regla general para los principiantes que no deseen ocuparse de las peculiaridades de los enlaces. la función en línea debe ser llamada por otra función en las mismas unidades de compilación. Si desea implementar una función en línea que se pueda usar en varias unidades de compilación, conviértalo en un archivo de encabezado declarado e implementado en línea.

¿Por qué?

Ejemplo: en el archivo de cabecera inlinetest.h

int foo(); 
inline int bar(); 

En la unidad de compilación inlinetest.cpp

int foo(){ int r = bar(); return r; } 


inline int bar(){ return 5;}; 

Luego, al main.cpp

#include "inlinetest.h" 
int main() 
{ 
    foo(); 
//bar(); 
    } 

Compilar archivo de un objeto a la vez Si elimina el comentario de esa llamada de "barra", tendrá un error. Porque la función en línea solo se implementa en el archivo de objeto inlinetest.o y no se exporta. Al mismo tiempo, la función foo, muy probablemente tiene incorporado el código de la función de barra (ya que la barra es una sola línea sin operación de E/S, entonces es muy probable que esté en línea)

Pero si en el archivo de encabezado tenía declaró la función en línea y la implementó en línea, entonces usted podría usarla en cualquier unidad de compilación que incluya ese encabezado. ("muestra de código");

Elimine la palabra clave en línea y el compilador NO provocará el error incluso con la llamada de barra en main Y no se realizará la línea a menos que solicite al compilador que incorpore todas las funciones.Ese no es un comportamiento estándar en la mayoría de los compiladores.

20

Significa una cosa y una sola cosa: que el compilador eliminará múltiples definiciones de la función.

Normalmente, una función no puede definirse varias veces (es decir, si coloca una definición de función no en línea en un encabezado y luego #include en varias unidades de compilación, recibirá un error de enlazador). Marcar la definición de función como "en línea" suprime este error (el enlazador asegura que ocurre lo correcto).

NO SIGNIFICA NADA MÁS!

Más significativamente, NO significa que el compilador incorporará la función compilada en cada sitio de llamadas. Si eso ocurre depende totalmente de los caprichos del compilador, y generalmente el modificador en línea hace poco o nada para cambiar la mente del compilador. El compilador puede, y lo hace, las funciones en línea que no son marcadas en línea, y puede realizar llamadas a funciones que están marcadas en línea.

Elidando múltiples definiciones es lo que debe recordar.

+0

Los compiladores solo en línea no están marcados como funciones en línea SOLAMENTE si así lo solicita. La palabra clave en línea sí afecta eso. Lo sé, he trabajado mucho en el código GCC que hace eso para producir una especialización del compilador en la universidad. – OldMan

+7

También he trabajado en GCC. En este cartel es básicamente correcto. Esta publicación debe estar en la parte superior de la lista. –

+0

Es correcto solo en los casos de la casusa. Inline no genera ninguna información adicional que el enlazador pueda usar. Compiel 2 archivos de objeto y verificación. ¡Permite múltiples definiciones exactas porque los símbolos no se exportan! ¡No porque ese sea su objetivo! – OldMan

3

@OldMan

Los compiladores única línea no marcados como funciones en línea SOLAMENTE si solicita que lo haga.

Solo si por "solicitud" quiere decir "activar las optimizaciones".

Es correcto solo en los casos de la casusa.

Es correcto en ambos.

Inline no genera ninguna información adicional que el enlazador pueda usar. Compiel 2 archivos de objeto y verificación. ¡Permite múltiples definiciones exactas porque los símbolos no se exportan! ¡No porque ese sea su objetivo!

¿Qué quiere decir con "los símbolos no se exportan"? las funciones en línea no son estáticas. Sus nombres son visibles; ellos tienen un enlace externo. Para citar del estándar de C++:

void h(); inline void h(); // enlace externo

inline void l(); void l(); // enlace externo

El objetivo de las definiciones múltiples es en gran medida el objetivo. Es obligatorio:

una función en línea se definirá en cada unidad de traducción en el que se utiliza y tendrá exactamente el misma definición en todos los casos (3,2). [Nota: se puede encontrar una llamada a la función en línea antes de que aparezca su definición en la unidad de traducción. ] Si una función con enlace externo se declara en línea en una unidad de traducción , se declarará en línea en todas las unidades de traducción en las que aparece; no se requiere diagnóstico.Una función en línea con enlace externo tendrá la misma dirección en todas las unidades de traducción.

Cuestiones relacionadas