txt manejo lenguaje leer headers guardar fputs ejercicios ejemplos datos cabecera binarios archivos archivo c++ performance header-files

c++ - manejo - headers en c



DefiniciĆ³n de la funciĆ³n de escritura en archivos de encabezado en C++ (7)

C ++ no se quejará si lo hace, pero en general, no debería.

cuando #incluye un archivo, todo el contenido del archivo incluido se inserta en el punto de inclusión. Esto significa que cualquier definición que ponga en su encabezado se copiará en cada archivo que incluya ese encabezado.

Para proyectos pequeños, no es probable que sea un gran problema. Pero para proyectos más grandes, esto puede hacer que las cosas tarden más tiempo en compilarse (ya que el mismo código se vuelve a compilar cada vez que se encuentra) y podría aumentar significativamente el tamaño del ejecutable. Si realiza un cambio en una definición en un archivo de código, solo ese archivo .cpp necesita ser recompilado. Si realiza un cambio en una definición en un archivo de encabezado, cada archivo de código que incluya el encabezado debe ser recompilado. ¡Un pequeño cambio puede hacer que tengas que recompilar todo tu proyecto!

A veces se hacen excepciones para funciones triviales que es poco probable que cambien (por ejemplo, donde la definición de la función es una línea).

Tengo una clase que tiene muchas funciones pequeñas. Por funciones pequeñas, me refiero a funciones que no procesan sino que simplemente devuelven un valor literal. Algo como:

string Foo::method() const{ return "A"; }

He creado un archivo de encabezado "Foo.h" y el archivo de origen "Foo.cpp". Pero dado que la función es muy pequeña, estoy pensando en ponerla en el archivo de encabezado. Tengo las siguientes preguntas:

  1. ¿Hay algún rendimiento u otros problemas si pongo esta definición de función en el archivo de encabezado? Tendré muchas funciones como esta.
  2. Según tengo entendido, cuando la compilación finalice, el compilador expandirá el archivo de encabezado y lo colocará donde está incluido. ¿Es eso correcto?

  1. Si sus funciones son así de simples, hágalo en línea, y tendrá que pegarlas en el archivo de encabezado de todos modos. Aparte de eso, cualquier convención es solo eso: convenciones.

  2. Sí, el compilador expande el archivo de encabezado donde encuentra las instrucciones #include.


Debe usar funciones en línea. Lea estas funciones en línea para una mejor comprensión y las compensaciones involucradas.


Depende de los estándares de codificación que se apliquen en su caso pero:

Las funciones pequeñas sin bucles y cualquier otra cosa deben estar incorporadas para un mejor rendimiento (pero un código ligeramente más grande, importante para algunas aplicaciones limitadas o integradas).

Si tiene el cuerpo de la función en el encabezado, lo tendrá por defecto en línea (d) (lo cual es bueno cuando se trata de velocidad).

Antes de que el compilador cree el archivo objeto, se llama al preprocesador (opción -E para gcc) y el resultado se envía al compilador que crea el objeto fuera del código.

Entonces la respuesta más corta es:

- Declarar funciones en el encabezado es bueno para la velocidad (pero no para el espacio) -


Dependiendo de su compilador y su configuración, puede hacer cualquiera de los siguientes:

  • Puede ignorar la palabra clave en línea (es solo una pista para el compilador, no un comando) y generar funciones independientes. Puede hacer esto si sus funciones superan un umbral de complejidad dependiente del compilador. por ejemplo, demasiados bucles anidados.
  • Puede decidir que su función independiente es un buen candidato para la expansión en línea.

En muchos casos, el compilador se encuentra en una posición mucho mejor para determinar si una función debe estar dentro de ti que tú, por lo que no tiene sentido cuestionarla. Me gusta usar la inclusión implícita cuando una clase tiene muchas funciones pequeñas solo porque es conveniente tener la implementación allí mismo en la clase. Esto no funciona tan bien para funciones más grandes.

La otra cosa a tener en cuenta es que si está exportando una clase en una biblioteca DLL / compartida (no es una buena idea en mi humilde opinión, pero la gente lo hace de todos modos), debe ser muy cuidadoso con las funciones en línea. Si el compilador que creó la DLL decide que una función debe estar en línea, tiene un par de problemas potenciales:

  1. El compilador que crea el programa utilizando el DLL podría decidir no alinear la función, por lo que generará una referencia de símbolo a una función que no existe y el DLL no se cargará.
  2. Si actualiza la DLL y cambia la función en línea, el programa cliente seguirá utilizando la versión anterior de esa función, ya que la función se introdujo en el código del cliente.

Si la función es pequeña (la posibilidad de que la cambie a menudo es baja), y si la función se puede poner en el encabezado sin incluir miríadas de otros encabezados (porque su función depende de ellos), es perfectamente válido hacerlo. Si los declaras extern en línea, entonces el compilador debe darle la misma dirección para cada unidad de compilación:

headera.h :

inline string method() { return something; }

Las funciones de miembro están implícitas en línea siempre que estén definidas dentro de su clase. Lo mismo es cierto para ellos: si pueden colocarse en el encabezado sin complicaciones, de hecho puede hacerlo.

Debido a que el código de la función se coloca en el encabezado y es visible, el compilador puede hacer llamadas en línea, es decir, poner el código de la función directamente en el sitio de la llamada (no tanto porque usted puso en línea antes, sino más porque el compilador decide de esa manera, sin embargo. Poner en línea solo es una pista para el compilador con respecto a eso). Eso puede dar como resultado una mejora en el rendimiento, porque el compilador ahora ve donde los argumentos coinciden con las variables locales para la función, y donde el argumento no se alía entre sí, y por último pero no menos importante, la asignación del marco de función ya no es necesaria.

Según tengo entendido, cuando la compilación finalice, el compilador expandirá el archivo de encabezado y lo colocará donde está incluido. ¿Es eso correcto?

Si, eso es correcto. La función se definirá en cada lugar donde incluya su encabezado. Al compilador le importará poner solo una instancia del mismo en el programa resultante, eliminando los demás.


Habrá un aumento en el rendimiento porque la implementación en los archivos de encabezado está implícitamente en línea. Como usted mencionó que sus funciones son pequeñas, la operación en línea será tan beneficiosa para usted en mi humilde opinión.

Lo que dices sobre el compilador también es cierto. No hay diferencia para el compilador, salvo para la línea, entre el código en el archivo de encabezado o el archivo .cpp .