Compartilhar via


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 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 maneira 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 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 pela velocidade e robustez de processamento do compilador, sendo a mais lenta e menos robusta, e sendo #include a mais rápida e import robusta.

Método Resumo
#include Uma desvantagem é que eles expõem macros e implementação interna. A implementação interna é frequentemente 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, em seguida, 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. Esta é uma melhoria na reconstruçã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 do que #include o import.
Unidades de cabeçalho Este é 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 o , e são mais fáceis de manter, significativamente menores e também mais rápidas do que #includeos 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 a importação de um módulo nomeado.

As unidades de cabeçalho não são afetadas pelas 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, 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 Esta é 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 C++23 apresenta os dois módulos nomeados descritos neste tópico.

Ao importar stdo , você obtém os nomes padrão, como , , mas sem extensões, sem auxiliares internos, como std::vector_Sort_unchecked, std::coute sem macros.

A ordem das importações não importa porque não há macro ou outros efeitos colaterais.

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 arquivo e um .ifc.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 por causa de como os módulos nomeados são independentes de ordem e macro - então esse trabalho não precisa ser feito quando o .ifc módulo é importado. Por outro lado, quando um arquivo de cabeçalho é consumido com #includeo , seu conteúdo deve ser pré-processado e compilado repetidamente em cada unidade de tradução.

Os cabeçalhos pré-compilados, que são instantâneos de memória do compilador, podem reduzir 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 em C++
Tutorial: Importar a biblioteca padrão do 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++