Condividi tramite


Confrontare unità di intestazione, moduli e intestazioni precompilate

Storicamente, si includerà la libreria standard con una direttiva come #include <vector>. Tuttavia, è costoso includere i file di intestazione perché vengono elaborati da ogni file di origine che li include.

Le intestazioni precompilate (PCH) sono state introdotte per velocizzare la compilazione convertendole una sola volta e riutilizzando il risultato. Ma le intestazioni precompilate possono essere difficili da gestire.

In C++20, i moduli sono stati introdotti come un miglioramento significativo dei file di intestazione e delle intestazioni precompilate.

Le unità di intestazione sono state introdotte in C++20 come modo per colmare temporaneamente il divario tra i file di intestazione e i moduli. Offrono alcuni dei vantaggi di velocità e affidabilità dei moduli, mentre si esegue la migrazione del codice per l'uso dei moduli.

La libreria standard C++23 ha quindi introdotto il supporto per l'importazione della libreria standard come moduli denominati. Questo è il modo più rapido e affidabile per utilizzare la libreria standard.

Per semplificare l'ordinamento delle diverse opzioni, questo articolo confronta il metodo tradizionale #include con intestazioni precompilate, unità di intestazione e importazione di moduli denominati.

La tabella seguente è disposta in base alla velocità di elaborazione del compilatore e alla robustezza, con #include il livello più lento e meno robusto e import il più veloce e affidabile.

Method Riepilogo
#include Uno svantaggio è che espongono macro e implementazione interna. L'implementazione interna viene spesso esposta come funzioni e tipi che iniziano con un carattere di sottolineatura. Si tratta di una convenzione per indicare che un elemento fa parte dell'implementazione interna e non deve essere usato.

I file di intestazione sono fragili perché l'ordine di #includes può modificare il comportamento o interrompere il codice e sono influenzati dalle definizioni di macro.

I file di intestazione rallentano la compilazione. In particolare quando più file includono lo stesso file perché il file di intestazione viene rielaborato più volte.
Intestazione precompilata Un'intestazione precompilata (PCH) migliora il tempo di compilazione creando uno snapshot di memoria del compilatore di un set di file di intestazione. Si tratta di un miglioramento della ricompilazione ripetuta dei file di intestazione.

I file PCH hanno restrizioni che li rendono difficili da gestire.

I file PCH sono più veloci ma #include più lenti rispetto a import.
Unità di intestazione Si tratta di una nuova funzionalità di C++20 che consente di importare file di intestazione "ben comportati" come moduli.

Le unità di intestazione sono più veloci di #includee sono più facili da gestire, notevolmente più piccole e anche più veloci rispetto ai file di intestazione precompilato (PCH).

Le unità di intestazione sono un passaggio 'in-between' che consente di passare a moduli denominati nei casi in cui si fa affidamento su macro definite nei file di intestazione, poiché i moduli denominati non espongono macro.

Le unità di intestazione sono più lente rispetto all'importazione di un modulo denominato.

Le unità di intestazione non sono interessate dalle definizioni di macro, a meno che non siano specificate nella riga di comando quando l'unità di intestazione li rende più affidabili rispetto ai file di intestazione.

Le unità di intestazione espongono le macro e l'implementazione interna definite in essi esattamente come fanno i file di intestazione, che i moduli denominati non lo fanno.

Come approssimazione approssimativa delle dimensioni del file, un file PCH da 250 megabyte potrebbe essere rappresentato da un file di unità di intestazione da 80 megabyte.
moduli Questo è il modo più veloce e affidabile per importare funzionalità.

Il supporto per l'importazione dei moduli è stato introdotto in C++20. La libreria standard C++23 introduce i due moduli denominati descritti in questo argomento.

Quando si importa std, si ottengono i nomi standard, std::vectorad esempio , std::cout, , ma nessuna estensione, nessun helper interno, ad _Sort_uncheckedesempio , e nessuna macro.

L'ordine delle importazioni non è importante perché non esistono macro o altri effetti collaterali.

Come approssimazione approssimativa delle dimensioni del file, un file PCH da 250 megabyte potrebbe essere rappresentato da un file di unità di intestazione da 80 megabyte, che potrebbe essere rappresentato da un modulo da 25 megabyte.

I moduli denominati sono più veloci perché quando un modulo denominato viene compilato in un .ifc file e in un .obj file, il compilatore genera una rappresentazione strutturata del codice sorgente che può essere caricata rapidamente quando il modulo viene importato. Il compilatore può eseguire alcune operazioni (ad esempio la risoluzione dei nomi) prima di emettere il .ifc file a causa del modo in cui i moduli denominati sono indipendenti dall'ordine e indipendente dalla macro, quindi questo lavoro non deve essere eseguito quando il modulo viene importato. Al contrario, quando un file di intestazione viene utilizzato con #include, il relativo contenuto deve essere pre-elaborato e compilato di nuovo e di nuovo in ogni unità di conversione.

Le intestazioni precompilate, che sono snapshot di memoria del compilatore, possono ridurre i costi, ma non i moduli denominati.

Se puoi usare le funzionalità di C++20 e la libreria standard C++23 nella tua app, usa moduli denominati.

Se è possibile usare le funzionalità di C++20, ma si vuole passare nel tempo ai moduli, usare le unità di intestazione nel frattempo.

Se non è possibile usare le funzionalità di C++20, usare e prendere #include in considerazione le intestazioni precompilate.

Vedi anche

File di intestazione precompilati
Panoramica dei moduli in C++
Esercitazione: Importare la libreria standard C++ usando i moduli
Procedura dettagliata: Importare librerie STL come unità di intestazione
Procedura dettagliata: Compilare e importare unità di intestazione nei progetti Visual C++