c++ - solo - ¿Hay implicaciones de rendimiento para incluir cada encabezado?
pie de pagina diferente en cada hoja word 2016 (5)
Digamos que quiero usar la función hex()
. Sé que está definido en el encabezado <ios>
y también sé que está incluido en el encabezado <iostream>
. La diferencia es que en <iostream>
hay muchas más funciones y otras cosas que no necesito.
Desde el punto de vista del rendimiento, ¿debería importarme incluir / definir menos funciones, clases, etc. que más?
Incluyendo encabezados innecesarios tiene siguientes desventajas.
- Un tiempo de compilación más largo, el enlazador debe eliminar todos los símbolos no utilizados.
- Si ha agregado encabezados adicionales en CPP, solo afectará su código.
- Pero si está distribuyendo su código como una biblioteca y ha agregado encabezados innecesarios en sus archivos de encabezado. El código del cliente se cargará con la ubicación de los encabezados que ha utilizado.
- No confíe en la inclusión indirecta, use el encabezado en el que realmente se define la función requerida.
- También en un proyecto como una buena práctica de programación, los encabezados deben incluirse en orden de reducir la dependencia.
//local header -- most dependent on other headers #include <project/impl.hpp> //Third party library headers -- moderately dependent on other headers #include <boost/optional.hpp> //standard C++ header -- least dependent on other header #include <string>
Y las cosas que no se verán afectadas son el tiempo de ejecución, el vinculador eliminará los símbolos no utilizados durante la compilación.
La inclusión de archivos de encabezado innecesarios tiene algún valor.
Se requiere menos esfuerzo de codificación para incluir un corte y pegado de los
include
usualmente necesarios. Por supuesto, la codificación posterior ahora se ve dificultada por no saber lo que realmente se necesitaba.Especialmente en C, con su control de espacio de nombres limitado, incluidos los encabezados innecesarios que detectan rápidamente las colisiones. El código Say definió una variable o función global no
static
que coincidía con el estándar, comoerfc()
para realizar un procesamiento de texto. Al incluir<math.h>
, la colisión se detecta condouble erfc(double x)
, a pesar de que este archivo.c
no hace FP FP pero otros archivos.c
hacen.#include <math.h> char *erfc(char *a, char *b);
OTOH, si este archivo .c
no estuviera incluido <math.h>
, en el momento del enlace, se detectaría la colisión. El impacto de este aviso retrasado podría ser grande si el código base durante años no necesitara FP matemática y ahora sí lo hace, solo para detectar char *erfc(char *a, char *b)
utilizado en muchos lugares.
OMI: haga un esfuerzo razonable para no incluir archivos de encabezado innecesarios, pero no se preocupe por incluir algunos adicionales, especialmente si son comunes. Si existe un método automatizado, utilícelo para controlar la inclusión del archivo de encabezado.
Si el estándar dice que está definido en el encabezado <ios>
entonces incluya el encabezado <ios>
porque no puede garantizar que se incluirá en / a través de cualquier otro encabezado.
TL; DR: En general, es mejor incluir solo lo que necesita. Incluir más puede tener un efecto adverso en el tamaño binario y en el inicio (debe ser insignificante), pero en general daña el tiempo de compilación sin encabezados precompilados.
Bueno, naturalmente, tiene que incluir al menos esas cabeceras juntas garantizadas para cubrir todos sus usos.
A veces puede suceder que "funcione" de todos modos, porque todos los encabezados de C ++ estándar pueden incluirse entre sí cuando el implementador lo desee, y los encabezados también pueden incluir símbolos adicionales en el std
names std
(ver Por qué está "utilizando el espacio de nombres std "considerado una mala práctica? ).
Luego, a veces, la inclusión de un encabezado adicional puede llevar a la creación de objetos adicionales (ver std::ios_base::Init
), aunque una biblioteca bien diseñada minimiza tales (esa es la única instancia en la biblioteca estándar, que yo sepa) .
Pero el gran problema no es en realidad el tamaño y la eficiencia del binario compilado (y optimizado) (que no debería verse afectado, aparte del punto anterior, cuyo efecto debería ser minúsculo), sino el tiempo de compilación mientras se desarrolla activamente (vea también Cómo funciona). #include <bits / stdc ++. h> funciona en C ++? ).
Y el último es (severamente, tanto que el comité está trabajando en una propuesta de módulos, vea Módulos C ++, ¿por qué se eliminaron de C ++ 0x? ¿Volverán más tarde? ) Afectados negativamente al agregar encabezados superfluos.
A menos que, naturalmente, esté utilizando encabezados precompilados (consulte ¿Por qué usar encabezados precompilados (C / C ++)? ), En cuyo caso se incluyen más en los encabezados precompilados y, por lo tanto, en todas partes, en lugar de solo cuando sea necesario, siempre que esos encabezados no se modifiquen , en realidad reducirá los tiempos de compilación la mayor parte del tiempo.
Existe una herramienta basada en el argot para encontrar los encabezados mínimos, llamados include-what-you-use .
Analiza el Clang AST para decidir eso, que es tanto una fortaleza como una debilidad:
No es necesario que le enseñe todos los símbolos que un encabezado pone a su disposición, pero tampoco sabe si las cosas simplemente funcionaron de esa manera en esa revisión, o si son contractuales.
Por lo que necesita comprobar sus resultados.
- No hay un golpe de rendimiento en tiempo de ejecución.
- Sin embargo, podría haber un golpe de tiempo de compilación excesivo si se incluyen toneladas de encabezados innecesarios.
- Además, cuando se hace esto, puede crear recompilaciones innecesarias si, por ejemplo, se cambia un encabezado pero un archivo que no lo usa lo incluye.
En proyectos pequeños (con encabezados pequeños incluidos), esto no importa. A medida que un proyecto crece, puede.