¿Qué significa que una función de C ++ esté en línea?

Ver título: ¿qué significa para una función de C ++ estar en línea?

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

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

Debe tener en cuenta que esto no obliga al comstackdor a realizar la función en línea, y lo ignorará si considera que es una mala idea. Del mismo modo, el comstackdor 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, desde entonces obtiene un externo no resuelto si fue declarado en línea, a menos, por supuesto, que solo ese archivo cpp lo use )

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

Normalmente, una función no se puede definir varias veces (es decir, si coloca una definición de función no en línea en un encabezado y luego #include en múltiples unidades de comstackció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 comstackdor incorporará la función comstackda en cada sitio de llamadas. Si eso ocurre depende totalmente de los caprichos del comstackdor, y generalmente el modificador en línea hace poco o nada para cambiar la mente del comstackdor. El comstackdor puede, y lo hace, alinear funciones que no están marcadas en línea, y puede realizar llamadas a funciones que están marcadas en línea.

Elidir múltiples definiciones es lo que hay que recordar.

Además de las otras respuestas (perfectamente correctas) sobre las implicaciones de rendimiento de inline , en C ++ también debe tener en cuenta que esto le permite poner una función en un encabezado de manera segura:

 // 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 que el comstackdor solo incluye el cuerpo real de la función en el primer archivo de objeto que necesita una función invocable regular para comstackrse (normalmente porque se tomó su dirección, como mostré anteriormente).

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

 use_my_thing_again.obj : error LNK2005: "int __cdecl do_my_thing(int,int)" (?do_my_thing@@YAHHH@Z) already defined in use_my_thing.obj <...>\Scratch.exe : fatal error LNK1169: one or more multiply defined symbols found 

@Anciano

Los comstackdores solo se alinean en línea sin marcar como funciones en línea SOLAMENTE si así lo solicita.

Solo si por “solicitud” quiere decir “activar optimizaciones”.

Es correcto solo en los casos en 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 objective!

¿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 C ++:

void h (); vacío en línea h (); // enlace externo

vacío en línea l (); vacío l (); // enlace externo

Lo de las definiciones múltiples es en gran medida el objective. Es obligatorio:

Se debe definir una función en línea en cada unidad de traducción en la que se utiliza y debe tener exactamente la misma definición en cada caso (3.2). [Nota: se puede encontrar una llamada a la función en línea antes de que su definición aparezca 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 debe tener la misma dirección en todas las unidades de traducción.

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.

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

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 comstackdor. En mi experiencia, la mayoría de los comstackdores modernos son buenos para determinar cuándo cumplir con la solicitud de un usuario de estar en línea.

En muchos casos, al establecer una función mejorará su rendimiento. Hay una sobrecarga inherente a las llamadas de función. Sin embargo, hay razones por las que incluir una función puede ser negativo:

  • Aumentar el tamaño del ejecutable binario mediante la duplicación de código podría llevar a la agitación del disco, ralentizando la aplicación.
  • El código de entrada podría contribuir a errores de caché, o posiblemente contribuir a hits de caché dependiendo de su architecture.

Las preguntas frecuentes de C ++ hacen un buen trabajo al explicar las complejidades de la palabra clave: http://www.parashift.com/c++faq-lite/inline-functions.html#faq-9.3

De manera informal, significa que los comstackdores pueden injertar los contenidos de la función en el sitio de llamadas, de modo que no haya llamadas a funciones. Si su función tiene grandes instrucciones de control (por ejemplo, if , switch , etc.) y las condiciones se pueden evaluar en el momento de la comstackció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 twigs no utilizadas se dejan caer).

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

Llamar a una función impone una cierta penalización de rendimiento para la CPU por el simple hecho de tener una secuencia 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 comstackdor 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 .

El comstackdor puede insertar una función que marca como en línea. No hay garantía de que el comstackdor lo haga. El comstackdor usa semántica compleja en el dispositivo cuando lo hace o no.

Cuando el comstackdor 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 stack, 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 suele ser el resultado de 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 comstackdor, que no necesita seguir. El comstackdor intentará hacer lo mejor.

Como regla general para principiantes que no quieren lidiar con peculiaridades de vinculación. la función en línea debe ser llamada por otra función en las mismas unidades de comstackción. Si desea implementar una función en línea que se pueda usar en varias unidades de comstackció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 comstackción inlinetest.cpp

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

Luego, en main.cpp

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

Comstack un archivo de 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 haya incrustado en ella el código de la función de la 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 había declarado la función en línea y la implementó en línea, entonces podría usarla en cualquier unidad de comstackción que incluya ese encabezado. (“muestra de código”);

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