Delen via


Header-eenheden, modules en precompiled headers vergelijken

In het verleden zou u met een richtlijn zoals #include <vector> de standaardbibliotheek opnemen. Het is echter duur om headerbestanden op te nemen omdat ze worden verwerkt door elk bronbestand dat ze bevat.

Vooraf gecompileerde headers (PCH) zijn geïntroduceerd om de compilatie te versnellen door ze eenmaal te vertalen en het resultaat opnieuw te gebruiken. Maar vooraf gecompileerde headers kunnen moeilijk te onderhouden zijn.

In C++20 zijn modules geïntroduceerd als een aanzienlijke verbetering van headerbestanden en vooraf gecompileerde headers.

Header-eenheden zijn in C++20 geïntroduceerd als een manier om de kloof tussen headerbestanden en modules tijdelijk te overbruggen. Ze bieden enkele van de snelheids- en robuustheidsvoordelen van modules, terwijl u uw code migreert om modules te gebruiken.

Vervolgens heeft de standaardbibliotheek van C++23 ondersteuning geïntroduceerd voor het importeren van de standaardbibliotheek als benoemde modules. Dit is de snelste en meest robuuste manier om de standaardbibliotheek te gebruiken.

Om u te helpen bij het sorteren van de verschillende opties, vergelijkt dit artikel de traditionele #include methode met vooraf gecompileerde headers, headereenheden en het importeren van benoemde modules.

De volgende tabel is gerangschikt op de verwerkingssnelheid en robuustheid van de compiler, met #include de traagste en minst robuuste en import snelste en meest robuuste.

Methode Samenvatting
#include Een nadeel is dat ze macro's en interne implementatie beschikbaar maken. Interne implementatie wordt vaak weergegeven als functies en typen die beginnen met een onderstrepingsteken. Dat is een conventie om aan te geven dat iets deel uitmaakt van de interne implementatie en niet mag worden gebruikt.

Headerbestanden zijn kwetsbaar omdat de volgorde van #includes gedrag kan wijzigen of code kan verbreken en wordt beïnvloed door macrodefinities.

Het compileren van headerbestanden wordt traag. Met name wanneer meerdere bestanden hetzelfde bestand bevatten, omdat het headerbestand meerdere keren opnieuw wordt verwerkt.
Vooraf gecompileerde header Een vooraf gecompileerde header (PCH) verbetert de compilatietijd door een momentopname van het compilergeheugen van een set headerbestanden te maken. Dit is een verbetering bij het herhaaldelijk herbouwen van headerbestanden.

PCH-bestanden hebben beperkingen waardoor ze moeilijk te onderhouden zijn.

PCH-bestanden zijn sneller dan #include maar langzamer dan import.
Koptekstsecties Dit is een nieuwe functie in C++20 waarmee u headerbestanden met een goed gedrag als modules kunt importeren.

Header-eenheden zijn sneller dan #includeen zijn eenvoudiger te onderhouden, aanzienlijk kleiner en ook sneller dan vooraf gecompileerde headerbestanden (PCH).

Header-eenheden zijn een 'tussenstap' die bedoeld is om te helpen bij de overgang naar benoemde modules in gevallen waarin u afhankelijk bent van macro's die in headerbestanden zijn gedefinieerd, aangezien benoemde modules geen macro's openbaar maken.

Header-eenheden zijn langzamer dan het importeren van een benoemde module.

Kopteksteenheden worden niet beïnvloed door macrodefinities, tenzij deze worden opgegeven op de opdrachtregel wanneer de kopteksteenheid wordt gebouwd, waardoor ze robuuster zijn dan headerbestanden.

Header-eenheden maken de macro's en interne implementatie beschikbaar die hierin zijn gedefinieerd, net zoals headerbestanden dat doen, wat benoemde modules niet doen.

Als ruwe benadering van de bestandsgrootte kan een PCH-bestand van 250 megabyte worden vertegenwoordigd door een header-eenheidsbestand van 80 megabyte.
Modules Dit is de snelste en meest robuuste manier om functionaliteit te importeren.

Ondersteuning voor het importeren van modules is geïntroduceerd in C++20. De C++23-standaardbibliotheek introduceert de twee benoemde modules die in dit onderwerp worden beschreven.

Wanneer u importeert std, krijgt u de standaardnamen zoals std::vector, std::coutmaar geen extensies, geen interne helpers zoals _Sort_uncheckeden geen macro's.

De volgorde van de invoer maakt niet uit omdat er geen macro of andere bijwerkingen zijn.

Als ruwe benadering van de bestandsgrootte kan een PCH-bestand van 250 megabyte worden vertegenwoordigd door een header-eenheidsbestand van 80 megabyte, dat mogelijk wordt vertegenwoordigd door een module van 25 megabyte.

Benoemde modules zijn sneller omdat wanneer een benoemde module wordt gecompileerd in een .ifc bestand en een .obj bestand, de compiler een gestructureerde weergave van de broncode verzendt die snel kan worden geladen wanneer de module wordt geïmporteerd. De compiler kan werk doen (zoals naamomzetting) voordat het .ifc bestand wordt verzonden vanwege hoe benoemde modules orderonafhankelijk en macro-onafhankelijk zijn. Dit werk hoeft dus niet te worden uitgevoerd wanneer de module wordt geïmporteerd. Wanneer daarentegen een headerbestand wordt gebruikt met #include, moet de inhoud ervan telkens in elke vertaaleenheid opnieuw worden voorverwerkt en gecompileerd.

Vooraf gecompileerde headers, die momentopnamen van compilergeheugen zijn, kunnen deze kosten beperken, maar niet zo goed als benoemde modules.

Als u C++20-functies en de C++23-standaardbibliotheek in uw app kunt gebruiken, gebruikt u benoemde modules.

Als u C++20-functies kunt gebruiken maar geleidelijk wilt overstappen op modules, gebruik dan in de tussentijd header units.

Als u geen C++20-functies kunt gebruiken, kunt u vooraf gecompileerde headers gebruiken #include en overwegen.

Zie ook

Vooraf gecompileerde headerbestanden
Overzicht van modules in C++
Zelfstudie: De standaardbibliotheek van C++ importeren met behulp van modules
Handleiding: STL-bibliotheken importeren als header-eenheden
Handleiding: Header-eenheden bouwen en importeren in uw Microsoft C++-projecten