Supuestos
Una de las ventajas de las bibliotecas de solo encabezado para C ++ es que no necesitan compilarse por separado.
En C y C ++
inline
tiene sentido solo si la función se define en un archivo de encabezado *.Tradicionalmente, en C, se ha utilizado el diseño .c / .h, donde el encabezado representa la interfaz pública mínima de la unidad de traducción. Del mismo modo, .cpp / hpp.
Pregunta
¿Las bibliotecas de solo encabezado son generalmente más eficientes en cuanto a código y tiempo de ejecución que el diseño tradicional? Si es así, ¿se debe a una amplia línea u otras optimizaciones?
* - la definición de la función en un encabezado permite al compilador ver la implementación durante la compilación de cualquier unidad de traducción y prácticamente hace posible la inserción de código
Respuestas:
No, eso no es una ventaja, sino todo lo contrario: la parte principal de la biblioteca debe compilarse con la frecuencia que se incluye, no solo una vez. Eso generalmente aumentará los tiempos de compilación. Sin embargo, si se refiere a las ventajas que se enumeran aquí en Wikipedia : ese artículo habla de una disminución de los gastos administrativos en relación con todo el proceso de construcción, empaquetado y despliegue.
Esto depende del sistema compilador / enlazador, pero supongo que para la mayoría de los compiladores C y C ++ existentes esto es cierto.
Eso es mayormente correcto. Los encabezados de clase C ++ a menudo contienen más que la interfaz pública mínima: generalmente también contienen muchas cosas privadas. Para mitigar esto, se utilizan cosas como el idioma PIMPL . Esto es algo así como "lo contrario" de una biblioteca de solo encabezado, trata de minimizar el contenido del encabezado necesario.
Pero para responder a su pregunta principal: esto es una compensación. Cuanto más código de biblioteca se ponga en los archivos de encabezado, más posibilidades tendrá el compilador de optimizar el código para la velocidad (si esto realmente sucede, o si el incremento es notable, es una pregunta completamente diferente). Por otro lado, demasiado código en los encabezados aumenta el tiempo de compilación. Especialmente en grandes proyectos de C ++ esto puede convertirse en un problema grave, vea "Diseño de software C ++ a gran escala" de John Lakos , aunque el libro está un poco desactualizado y algunos de los problemas descritos allí son abordados por compiladores modernos, las ideas generales / Las soluciones siguen siendo válidas.
En particular, cuando no está utilizando una biblioteca estable (de terceros), pero está desarrollando sus propias bibliotecas durante su proyecto, los tiempos de compilación se hacen evidentes. Cada vez que cambie algo en la biblioteca, debe cambiar un archivo de encabezado, lo que provocará una recompilación y vinculación de todas las unidades dependientes.
En mi humilde opinión, la popularidad de las bibliotecas de solo encabezado es causada por la popularidad de la meta programación de plantillas. Para la mayoría de los compiladores, las bibliotecas con plantilla deben ser solo de encabezado porque el compilador solo puede iniciar el proceso de compilación principal cuando se proporcionan los parámetros de tipo, y para una compilación y optimización completas, el compilador debe ver "ambos a la vez": el código de la biblioteca más la plantilla valores paramétricos. Eso hace que sea imposible (o al menos difícil) producir unidades de compilación "precompiladas" para dicha biblioteca.
fuente
Bueno, primero demuelemos algunos de sus supuestos:
Compilar cosas por separado significa potencialmente no tener que volver a compilar todo si solo cambia una parte.
Entonces, una desventaja en lugar de una ventaja.
Sí, el único efecto que
inline
queda es la excepción a la regla de una definición .¡Ay de ustedes si esas definiciones son diferentes de alguna manera!
Entonces, si una función es interna a una unidad de compilación, márquela
static
. Eso también hace que la alineación sea más probable, ya que la función debe estar disponible para alinearla.Aún así, eche un vistazo a la optimización del tiempo de enlace, como lo respaldan al menos MSVC ++, gcc y clang.
Bueno, solo presentar la interfaz mínima es sin duda uno de los objetivos, lograr una mayor estabilidad API y ABI, y minimizar los tiempos de compilación.
Sin embargo, especialmente las clases de C ++ no están realmente orientadas a eso, ya que todos los bits privados se filtran en el encabezado, al igual que los protegidos, ya sea que desee derivarlos o no.
El patrón de diseño PIMPL es para reducir tales detalles.
Sin embargo, la parte donde la separación de la interfaz y la implementación falla por completo en C ++ son las plantillas.
El comité intentó hacer algo con las plantillas exportadas , pero eso ha sido abandonado como demasiado complicado y realmente no funciona.
Ahora, están trabajando en un sistema de módulos adecuado , aunque es lento. Eso reduce drásticamente los tiempos de compilación, y también debería aumentar la estabilidad API y ABI al disminuir su superficie.
Las bibliotecas de solo encabezado pueden ser más eficientes en tamaño de código y tiempo de ejecución, aunque eso depende de si la biblioteca se comparte, cuánto se usa, de qué maneras y si la inclusión en línea demuestra una victoria decisiva en ese caso específico.
Y la razón por la que la alineación es tan importante para la optimización no es porque la alineación en sí misma sea un gran impulso, sino que se abre debido a las oportunidades de propagación constante y una mayor optimización.
fuente