2010-07-27 6 views
13

acabo de tener una discusión con un compañero de trabajo en relación con el código en archivos de cabecera:¿El código en los archivos de encabezado siempre estará en línea?

Se dice que el código se define en los archivos de cabecera siempre ser inline por el compilador (como el código de la obtieneNumero() en mi ejemplo cabecera) . Digo que se insertará a veces, siempre que el compilador decida hacerlo. Entonces, ¿cuál de nosotros tiene que traer un pastel al trabajo por decir mentiras sucias? ¿O tal vez los dos estamos equivocados ...?

MyClass.hpp

class MyClass 
    { 
    public: 
    MyClass(); 
    ~MyClass(); 

    int GetNumber() const 
    { 
    //...; 
    return m_number; 
    }; 

    private: 
    int m_number; 
    }; 
+0

Gracias por todas las buenas respuestas. Esto ciertamente nos ayudó a mí y a mi compañero de trabajo a aclarar este tema. No obstante, no podemos decidir quién debe traer el pastel ... ;-) – nabulke

+0

¿Aceptaría que incluir líneas no depende de si la función está definida en un encabezado o no? – adf88

+0

Sí, estoy de acuerdo, con un comentario: realmente debe tener cuidado con lo que está hablando si usa el término 'en línea'. Si define una función miembro dentro de un archivo de encabezado, _será_ una función en línea (el lugar de la definición importa). Si esta función en línea se insertará posteriormente es, como ha señalado, hasta el compilador (el lugar de definición no importa). Creo que la respuesta de Mattis es una buena explicación de eso. – nabulke

Respuesta

10

Cualquier función definida dentro de la clase (como su ejemplo obtieneNumero) en lugar de sólo es declarada implícitamente inline. Lo que eso significa es que es equivalente al uso de la palabra clave inline, por lo que las inclusiones múltiples del encabezado no causarán errores de enlace debido a múltiples definiciones de esas funciones.

La mayoría de los compiladores modernos tratan inline como un comando de enlace y nada más. Algunos compiladores proporcionan palabras clave más fuertes, como CL __forceinline, que significan 'alinear esto si es posible hacerlo'.

Así que ambos tienen razón y ambos están equivocados hasta cierto punto.

+0

'así que las inclusiones múltiples del encabezado no causarán errores de enlace debido a múltiples definiciones de esas funciones. ¿Qué pasa si el compilador no decide sustituir la función en línea? ¿Sigue causando un error de enlace? – Deqing

+0

Marcar la función 'en línea' hace que el compilador no omita un error si ve múltiples definiciones idénticas de la función, independientemente de si la compilación elige alinear el código o no. –

1

eso no es verdad, va a ser inline único código en funciones miembro (en caso de que el compilador decide hacerlo) si se especifica dentro de la declaración de la clase. Sin embargo, debe permitir que los miembros se definan, por lo que se pueden declarar como el equivalente de C static (que permitirá su uso dentro de la unidad de compilación, pero no se puede vincular a otros archivos de objeto), lo que pondrá una versión en cada archivo de objeto. Inténtalo tú mismo, notarás que a menos que especifiques la palabra clave en línea para cualquier cosa que esté fuera de la declaración de clase, obtendrás duplicados.

1

El compilador decide. Incluso al usar _inline solo le dice al compilador que prefiere el código en línea, pero el analizador de costo/beneficio del compilador puede decidir lo contrario.

Puede usar _forceinline si está utilizando Microsoft C++ para hacer el código en línea, pero eso podría dar lugar a binarios más grandes.

+0

+1: no sabía acerca de _forceinline – nabulke

3

Esto depende de lo que quiere decir con "enlining". Si se define algo en un archivo de encabezado, se compilará por separado en cada unidad de compilación que lo incluya. Si cualquier llama a para que la función esté en línea dependerá del compilador.

7

Tu amigo está equivocado, tienes razón.

La alineación no depende de dónde está el código (encabezado o no). Después del preprocesamiento, no hay encabezados ni encabezados. Toda la unidad es un archivo único, contiene todo lo incluido.

intente ejecutar preprocesador GCC entonces verá:

gcc -E some_source_file_with_includes 
+5

La alineación depende de dónde está el código. Si el origen de una función se declara en otra unidad de traducción, no puede incluirse porque el compilador no puede ver la definición, a menos que tenga un compilador/enlazador que admita la optimización de todo el programa. –

+1

+1: me gustó su comentario sobre la unidad completa después del preprocesamiento – nabulke

+0

Escribí sobre ARCHIVOS DE ENCABEZADOS, no hay diferencia si la definición está dentro de un encabezado o no. Lea cuidadosamente. – adf88

2

función miembro de clase define (a diferencia de solamente a declarar) en la definición de clase son implícitamenteinline. Otro código en los encabezados no lo es.

Puede comprobar fácilmente esto: Crear un pequeño proyecto de C++ con una cabecera y dos archivos de aplicación, definir una función

void print(std::ostream& os) 
{ 
    os << "Hello, world!\n"; 
} 

en el encabezado e incluir esa cabecera en ambos archivos de implementación. El enlazador ahora se quejará de que la función se define dos veces. Ponga un inline antes de la definición de la función y el error desaparecerá.

Hay, sin embargo, algunas irregularidades más. Por ejemplo, una definición constante obtendrá automáticamente un enlace externo.Por lo tanto, un

const int answer = 42; 

en una cabecera no hará que el enlazador se quejan de múltiples definiciones de answer, mientras

int question; 

voluntad.

3

En realidad ambos son correctos. La forma en que ustedes se refirieron es un poco diferente. (supongo)

Desde el doc C++ estándar para la función en línea,

  1. Una declaración de la función (8.3.5, 9.3, 11.4 ) con un comitente en línea declara una función en línea.

2. Una función definida dentro de una definición de clase es una función en línea.

Así como dijo su colega, que es de hecho función en línea.

Pero el código de sustitución para la función en línea en lugar de la llamada a la función normal de depende del compilador. (Espero que esto sea lo que USTED quiere decir). Incluso si el compilador no lo sustituye, sigue siendo una función en línea.

espero que borra su preocupación ..

+0

La función en línea no tiene que estar en línea, la función no en línea puede estar en línea. Compilador decide. Además, estás hablando de detalles del ejemplo no relacionado con la pregunta. – adf88

+0

@ adf88, eso es lo que quise decir. La sustitución del código es decidida por el compilador, pero la función es de hecho una función en línea. Todas las funciones en línea no necesitan ser sustituidas por el compilador. – liaK

+0

La pregunta no trata sobre si la función está en línea (en lenguaje C++). Se trata de si la función será inline por el compilador. – adf88

Cuestiones relacionadas