Comparar unidades de cabeçalho, módulos e cabeçalhos pré-compilados
Historicamente, você incluiria a biblioteca padrão com uma diretiva como #include <vector>
. No entanto, é caro incluir arquivos de cabeçalho porque eles são reprocessados por todos os arquivos de origem que os incluem.
Cabeçalhos pré-compilados (PCH) foram introduzidos para acelerar a compilação, traduzindo-os uma vez e reutilizando o resultado. Mas os cabeçalhos pré-compilados podem ser difíceis de manter.
No C++20, os módulos foram introduzidos como uma melhoria significativa em arquivos de cabeçalho e cabeçalhos pré-compilados.
As unidades de cabeçalho foram introduzidas no C++20 como uma forma de preencher temporariamente a lacuna entre arquivos de cabeçalho e módulos. Eles fornecem alguns dos benefícios de velocidade e robustez dos módulos, enquanto você migra seu código para usar módulos.
Em seguida, a biblioteca padrão do C++23 introduziu suporte para importar a biblioteca padrão como módulos nomeados. Essa é a maneira mais rápida e robusta de consumir a biblioteca padrão.
Para ajudá-lo a classificar as diferentes opções, este artigo compara o método tradicional #include
com cabeçalhos pré-compilados, unidades de cabeçalho e importação de módulos nomeados.
A tabela a seguir é organizada por velocidade de processamento e robustez do compilador, sendo #include
a mais lenta e menos robusta e import
a mais rápida e robusta.
Método | Resumo |
---|---|
#include |
Uma desvantagem é que eles expõem macros e implementação interna. A implementação interna geralmente é exposta como funções e tipos que começam com um sublinhado. Essa é uma convenção para indicar que algo faz parte da implementação interna e não deve ser usado. Os arquivos de cabeçalho são frágeis porque a ordem de #includes pode modificar o comportamento ou quebrar o código e são afetados por definições de macro. Arquivos de cabeçalho compilação lenta. Particularmente quando vários arquivos incluem o mesmo arquivo, porque o arquivo de cabeçalho é reprocessado várias vezes. |
Cabeçalho pré-compilado | Um cabeçalho pré-compilado (PCH) melhora o tempo de compilação criando um instantâneo de memória do compilador de um conjunto de arquivos de cabeçalho. Essa é uma melhoria na recriação repetida de arquivos de cabeçalho. Os arquivos PCH têm restrições que os tornam difíceis de manter. Os arquivos PCH são mais rápidos, #include mas mais lentos que os import arquivos . |
Unidades de cabeçalho | Esse é um novo recurso no C++20 que permite importar arquivos de cabeçalho 'bem comportados' como módulos. As unidades de cabeçalho são mais rápidas do que #include o , e são mais fáceis de manter, significativamente menores e também mais rápidas do que os arquivos de cabeçalho pré-compilados (PCH).As unidades de cabeçalho são uma etapa "intermediária" destinada a ajudar na transição para módulos nomeados nos casos em que você depende de macros definidas em arquivos de cabeçalho, já que os módulos nomeados não expõem macros. As unidades de cabeçalho são mais lentas do que importar um módulo nomeado. As unidades de cabeçalho não são afetadas por definições de macro, a menos que sejam especificadas na linha de comando quando a unidade de cabeçalho é criada, tornando-as mais robustas do que os arquivos de cabeçalho. As unidades de cabeçalho expõem as macros e a implementação interna definidas nelas da mesma forma que o arquivo de cabeçalho, o que os módulos nomeados não expõem. Como uma aproximação aproximada do tamanho do arquivo, um arquivo PCH de 250 megabytes pode ser representado por um arquivo de unidade de cabeçalho de 80 megabytes. |
Módulos | Essa é a maneira mais rápida e robusta de importar funcionalidades. O suporte para importação de módulos foi introduzido no C++20. A biblioteca padrão do C++23 apresenta os dois módulos nomeados descritos neste tópico. Ao importar std o , você obtém os nomes padrão, como std::vector , std::cout , mas sem extensões, sem auxiliares internos, como _Sort_unchecked , e sem macros.A ordem das importações não importa porque não há efeitos colaterais macro ou outros. Como uma aproximação aproximada do tamanho do arquivo, um arquivo PCH de 250 megabytes pode ser representado por um arquivo de unidade de cabeçalho de 80 megabytes, que pode ser representado por um módulo de 25 megabytes. Os módulos nomeados são mais rápidos porque, quando um módulo nomeado é compilado em um .ifc arquivo e um .obj arquivo, o compilador emite uma representação estruturada do código-fonte que pode ser carregada rapidamente quando o módulo é importado. O compilador pode fazer algum trabalho (como resolução de nomes) antes de emitir o arquivo devido à forma como os .ifc módulos nomeados são independentes de ordem e macro - portanto, esse trabalho não precisa ser feito quando o módulo é importado. Por outro lado, quando um arquivo de cabeçalho é consumido com #include , seu conteúdo deve ser pré-processado e compilado repetidamente em cada unidade de tradução. Cabeçalhos pré-compilados, que são instantâneos de memória do compilador, podem mitigar esses custos, mas não tão bem quanto os módulos nomeados. |
Se você puder usar os recursos do C++20 e a biblioteca padrão do C++23 em seu aplicativo, use módulos nomeados.
Se você puder usar recursos do C++20, mas quiser fazer a transição ao longo do tempo para módulos, use unidades de cabeçalho nesse ínterim.
Se você não puder usar recursos do C++20, use #include
e considere cabeçalhos pré-compilados.
Confira também
Arquivos de cabeçalho pré-compilados
Visão geral dos módulos no C++
Tutorial: Importar a biblioteca padrão C++ usando módulos
Passo a passo: Importar bibliotecas STL como unidades de cabeçalho
Guia Passo a passo: compilar e importar unidades de cabeçalho em seus projetos do Visual C++