2012-04-11 15 views
25

¿Cuál es la diferencia entre usar la palabra clave en línea antes de una función y simplemente declarar toda la función en el encabezado?Palabra clave en línea frente a la definición del encabezado

así que ...

int whatever() { return 4; } 

vs

.h:

inline int whatever(); 

.cpp:

inline int myClass::whatever() 
{ 
    return 4; 
} 

para el caso, ¿Qué hace esto:

inline int whatever() { return 4; } 

Respuesta

10

sininline, es probable que terminar con múltiples símbolos exportados, si la función se declara en el espacio de nombres o global alcance (resultados en errores de enlace).

Sin embargo, para una clase (como se ve en su ejemplo), la mayoría de los compiladores declaran implícitamente el método como en línea (-fno-default-inline deshabilitará ese valor predeterminado en GCC).

si declara una función como en línea, el compilador puede esperar ver su definición en la traducción. por lo tanto, debe reservarlo para el momento en que la definición sea visible.

en un nivel superior: una definición en la declaración de clase es frecuentemente visible para más traducciones. esto puede dar como resultado una mejor optimización y puede dar como resultado un aumento de los tiempos de compilación.

a menos que la optimización manual y las compilaciones rápidas sean importantes, es inusual usar la palabra clave en una declaración de clase actualmente.

2

Esta pregunta explica mucho acerca de las funciones en línea What does __inline__ mean ? (a pesar de que estaba a punto línea palabra clave.)

Básicamente, no tiene nada que ver con la cabecera. Declarar toda la función en el encabezado solo cambia en qué archivo fuente tiene el origen de la función. Palabra clave en línea modifica dónde se colocará la función compilada resultante, en su propio lugar, para que cada llamada vaya allí, o en lugar de cada llamada (mejor para el rendimiento). Sin embargo, los compiladores algunas veces eligen qué funciones o métodos hacer en línea para ellos mismos, y las palabras clave son simplemente sugerencias para el compilador. Incluso las funciones que no se especificaron en línea pueden ser elegidas por el compilador para estar en línea, si eso ofrece un mejor rendimiento.

1

Si está vinculando varios objetos en un ejecutable, normalmente debería haber solo un objeto que contenga la definición de la función. Para int whatever() { return 4; } - cualquier unidad de traducción que se use para producir un objeto contendrá una definición (es decir, código ejecutable) para la función whatever. El vinculador no sabrá a cuál llamar a las personas que llaman. Si se proporciona inline, entonces el código ejecutable puede estar o no insertado en los sitios de llamadas, pero si no lo está, el vinculador puede suponer que todas las definiciones son las mismas, y elegir uno arbitrariamente para dirigir las llamadas a. Si de alguna manera las definiciones no son las mismas, entonces se considera SU culpa y obtiene un comportamiento indefinido.Para usar inline, la definición debe conocerse cuando compila la llamada, por lo que su idea de colocar una declaración en línea en un encabezado y la definición en línea en un archivo .cpp solo funcionará si todas las personas que llaman están más tarde en ese mismo .cpp archivo - en general está roto, y esperaría que la definición de la función en línea (nominalmente) aparezca en el encabezado que la declara (o para que haya una definición única sin declaración previa).

28

Hay varias facetas:

idioma

  • Cuando una función está marcado con la palabra clave inline, a continuación, su definición debe estar disponible en la TU o el programa está mal formadas.
  • Cualquier función definida directamente en la definición de clase está marcada implícitamente inline.
  • Una función marcada inline (implícita o explícitamente) se puede definir en varias TU (respetando el ODR), mientras que no es el caso para las funciones normales.
  • Las funciones de la plantilla (no totalmente especializadas) obtienen el mismo tratamiento que inline.

el comportamiento del compilador

  • Una función marcada inline se emitirá como un símbolo débil en cada fichero objeto donde es necesario, esto puede aumentar su tamaño (mirar hacia arriba hinchazón plantilla).
  • Mientras que el compilador en realidad inserta la llamada (es decir, copiar/pegar el código en el punto de uso en lugar de realizar una llamada de función normal) es completamente a discreción del compilador. La presencia de la palabra clave puede, o no, influir en la decisión, pero es, en el mejor de los casos, una sugerencia .

comportamiento Enlazador

  • símbolos débiles se fusionan juntos para tener una sola aparición en la biblioteca final. Un buen enlazador podría verificar que las múltiples definiciones coincidan, pero esto no es obligatorio.
+6

¿Qué quiere decir con "TU" y "ODR"? – WiSaGaN

+4

@WiSaGaN: TU = Unidad de traducción: más o menos, el archivo fuente preprocesado. ODR = Una Regla de Definición: se requiere que todas las definiciones de una función/clase sean idénticas, a nivel de personaje, a través de TU. –

+0

¿En el nivel de personaje o en el nivel de token? – fredoverflow

9

El propósito de inline es permitir una función que se define en más de una unidad de traducción, que es necesaria para algunos compiladores para poder inline donde quiera que se utiliza. Debe usarse siempre que defina una función en un archivo de encabezado, aunque puede omitirla al definir una plantilla, o una función dentro de una definición de clase.

Definirlo en un encabezado sin inline es una muy mala idea; si incluye el encabezado de más de una unidad de traducción, entonces rompe la Regla de una sola definición; es probable que su código no se vincule y, si lo hace, puede presentar un comportamiento indefinido.

Declararlo en un encabezado con inline pero definirlo en un archivo fuente también es una muy mala idea; la definición debe estar disponible en cualquier unidad de traducción que la use, pero al definirla en un archivo fuente, solo está disponible en una unidad de traducción. Si otro archivo fuente incluye el encabezado e intenta llamar a la función, entonces su programa no es válido.

Cuestiones relacionadas