2009-09-18 9 views
14

En C++, ¿los métodos solo se ingresan si se declaran explícitamente inline (o se definen en un archivo de encabezado), o se permite que los compiladores incorporen los métodos según lo consideren oportuno?¿Cuándo compilan los compiladores el código en C++?

+2

nota: inline es solo una pista para el compilador. El compilador no está obligado a alinearlo. –

+0

@Martin York: Desafortunadamente tienes razón. Y en el 99.9% de los casos, es mejor dejar que el compilador decida en última instancia. Pero en algunos casos (programas de rendimiento crítico como procesamiento de imágenes, etc.) sería bueno tener un último interruptor de forzado en línea. Pero puedo entender a los programadores de compiladores. Debido a que tan pronto como este interruptor existiría, muchos lo usarían en muchos casos inapropiados, sin importar cuán insistentemente la documentación advierta usarlo solo en casos raros ... – mmmmmmmm

+1

Más exactamente, 'inline' tiene un significado diferente en el código C/C++ que el usado para describir la optimización. En el código C/C++, 'inline' simplemente significa que pueden existir múltiples definiciones de una función, y que el enlazador debe unirlas de nuevo. No * significa * que las llamadas a esa función deben estar en línea. Son dos conceptos completamente separados. – jalf

Respuesta

21

Sí, el compilador puede codificar en línea incluso si no está explícitamente declarado como inline.

Básicamente, siempre que la semántica no se modifique, el compilador puede prácticamente hacer lo que quiera con el código generado. El estándar no obliga a nada especial en el código generado.

+2

Dado que el compilador hace todo por nosotros, ¿por qué necesitamos una pista en línea? –

+1

@lz_prgmr: Bueno, además del punto sutil mencionado por UncleBens a continuación, creo que no. Es importante tener en cuenta que los compiladores * * no eran tan listos desde el principio y estamos algo atrapados con las antiguas funciones del lenguaje. –

+0

Gracias, creo que la explicación tiene sentido: por razones históricas ... –

4

Si no me equivoco, cuando las optimizaciones están activadas, el compilador alineará cualquier rutina o método adecuado.

+0

"Activar optimizaciones" no es un término estándar. Está describiendo implementaciones reales, quién sí tiene ese interruptor. En ese caso, no necesita el _may_ hipotético: el compilador _incluirá funciones adecuadas. – MSalters

+0

@MSalters, tienes razón. –

5

Los compiladores pueden alinear cualquier función o no alinearla. Se les permite usar la decoración inline como una pista para esta decisión, pero también se les permite ignorarla.

También tenga en cuenta que las funciones miembro de clase tienen una decoración implícita inline si se definen en la definición de clase.

4

Los compiladores pueden ignorar su declaración en línea. Es básicamente utilizado por el compilador como una pista para decidir si lo hace o no. Los compiladores no están obligados a alinear algo que está marcado en línea, o no alinear algo que no está en línea. Básicamente, estás a merced de tu compilador y del nivel de optimización que elijas.

3

texto de información IBM Center,

Utilizando el comitente en línea es sólo una sugerencia al compilador que una expansión en línea puede llevar a cabo; el compilador es libre de ignorar la sugerencia .

C Idioma cualquier función, con la excepción de principal, puede ser declarado o define como en línea con la función de especificador inline . Las variables locales estáticas no pueden ser definidas dentro del cuerpo de una función en línea .

C++ funciones implementadas dentro de una declaración de clase son inline definen automáticamente. Regular C++ funciones y las funciones miembro declarados fuera de una declaración de la clase , con la excepción de principal, puede ser declarado o definido como en línea con el especificador de función en línea . Los locales estáticos y los literales de cadena definidos dentro del cuerpo de una función en línea se tratan como el mismo objeto en las unidades de traducción;

0

La palabra clave en línea es solo una solicitud al compilador. El compilador se reserva el derecho de realizar o no una función en línea. Uno de los principales factores que impulsa la decisión del compilador es la simplicidad del código (no muchos bucles)

Las funciones miembro son declarados en línea por defecto. (El compilador decide aquí también)

Estas no son reglas duras y rápidas .Varía según las implementaciones del compilador.

Si alguien conoce otros factores involucrados, por favor publique.

0

El compilador puede alinear lo que quiera en caso de que la alineación no viole la semántica del código y pueda alcanzar el código de la función. También puede alinear de forma selectiva: realice una línea cuando considere que es una buena idea y no en línea cuando no sienta que es una buena idea o cuando viole la semántica del código.

Algunos compiladores pueden hacer líneas internas incluso si la función está en otra unidad de traducción, que se conoce como generación de código de tiempo de enlace.

Los casos típicos de cuando la línea entrante violaría la semántica del código son llamadas virtuales y pasar una dirección de función a otra función o almacenarla.

1

El compilador optimiza como quiera a menos que especifique lo contrario.

+0

Haha el compilador es un hombre –

27

El línea palabra clave en realidad sólo le indica al enlazador (o le dice al compilador para decirle al enlazador) que las definiciones idénticas múltiples de la misma función no son un error. Lo necesitará si desea definir una función en un encabezado, o obtendrá errores de "definición múltiple" del vinculador, si el encabezado está incluido en más de una unidad de compilación.

La justificación de la elección línea como la palabra clave parece ser que la única razón por la que uno quiere definir una función (no molde) en un encabezado es por lo que podría ser inline por el compilador. El compilador no puede alinear una llamada de función, a menos que tenga la definición completa. Si la función no está definida en el encabezado, el compilador solo tiene la declaración y no puede alinear la función aunque lo desee.

Hoy en día, he oído que no solo el compilador optimiza el código, sino que también lo puede hacer el vinculador. Un enlazador podría (si no lo hacen ya) llamar a la función en línea incluso si la función no se definió en la misma unidad de compilación.

Y probablemente no sea una buena idea definir funciones mayores que quizás una sola línea en el encabezado (en absoluto para el tiempo de compilación, y si la función grande está enlineada, podría llevar a la hinchazón y peor rendimiento).

+0

+1 para señalar el "doble significado" de 'en línea' – peterchen

+1

Este es el aspecto realmente importante de en línea. –

2

La documentación de su compilador debe informarle ya que depende de la implementación. Por ejemplo, GCC de acuerdo con su manual nunca inserta ningún código a menos que se aplique optimización.

Si el compilador no coloca en línea del código, la línea palabra clave tendrá el mismo efecto que estática, y cada unidad de compilación que llama al código tendrá su propia copia. Un enlazador inteligente puede reducir estos a una sola copia.

0

Algunas de las situaciones en las que la expansión en línea puede no funcionar son:

  1. Para funciones que devuelven valores, si un lazo, un interruptor, o una Goto existe
  2. para la función de los valores no regresan, si un retorno declaración sale;
  3. Si las funciones contienen variables estáticas
  4. Si las funciones en línea son recursivas.

La expansión en línea hace que un programa se ejecute más rápido porque se elimina la sobrecarga de una declaración de función y devolución. Sin embargo, hace que el programa ocupe más memoria porque las instrucciones que definen las funciones en línea se reproducen en cada punto donde se llama a la función. Entonces, se necesita una compensación.

(como figura en uno de mis libros OOP)

Cuestiones relacionadas