Partage via


Comparer les unités d’en-tête, les modules et les en-têtes précompilés

Historiquement, vous incluez la bibliothèque standard avec une directive comme #include <vector>. Toutefois, il est coûteux d’inclure des fichiers d’en-tête, car ils sont traités par chaque fichier source qui les inclut.

Les en-têtes précompilés (PCH) ont été introduits pour accélérer la compilation en les convertissant une fois et en réutilisant le résultat. Mais les en-têtes précompilés peuvent être difficiles à gérer.

En C++20, les modules ont été introduits comme une amélioration significative des fichiers d’en-tête et des en-têtes précompilés.

Les unités d’en-tête ont été introduites en C++20 pour combler temporairement l’écart entre les fichiers d’en-tête et les modules. Ils offrent quelques-uns des avantages de la vitesse et de la robustesse des modules, tandis que vous migrez votre code pour utiliser des modules.

Ensuite, la bibliothèque standard C++23 a introduit la prise en charge de l’importation de la bibliothèque standard en tant que modules nommés. Il s’agit du moyen le plus rapide et le plus robuste d’utiliser la bibliothèque standard.

Pour vous aider à trier les différentes options, cet article compare la méthode traditionnelle #include par rapport aux en-têtes précompilés, aux unités d’en-tête et à l’importation de modules nommés.

Le tableau suivant est organisé par vitesse de traitement du compilateur et robustesse, étant #include le plus lent et le moins robuste, et import étant le plus rapide et le plus robuste.

Méthode Résumé
#include L’un des inconvénients est qu’ils exposent des macros et une implémentation interne. L’implémentation interne est souvent exposée en tant que fonctions et types qui commencent par un trait de soulignement. Il s’agit d’une convention qui indique que quelque chose fait partie de l’implémentation interne et ne doit pas être utilisé.

Les fichiers d’en-tête sont fragiles, car l’ordre de #includes peut modifier le comportement ou interrompre le code et sont affectés par les définitions de macros.

Les fichiers d’en-tête sont compilés lentement. En particulier lorsque plusieurs fichiers incluent le même fichier, car le fichier d’en-tête est retraché plusieurs fois.
En-tête précompilé Un en-tête précompilé (PCH) améliore le temps de compilation en créant une mémoire du compilateur instantané d’un ensemble de fichiers d’en-tête. Il s’agit d’une amélioration de la reconstruction répétée des fichiers d’en-tête.

Les fichiers PCH ont des restrictions qui les rendent difficiles à gérer.

Les fichiers PCH sont plus rapides que #include mais plus lents que import.
Unités d’en-tête Il s’agit d’une nouvelle fonctionnalité en C++20 qui vous permet d’importer des fichiers d’en-tête « bien comportementés » en tant que modules.

Les unités d’en-tête sont plus rapides que #include, et sont plus faciles à gérer, beaucoup plus petites et aussi plus rapides que les fichiers d’en-tête précompilés (PCH).

Les unités d’en-tête sont une étape « in-between » destinée à faciliter la transition vers des modules nommés dans les cas où vous vous appuyez sur des macros définies dans les fichiers d’en-tête, car les modules nommés n’exposent pas de macros.

Les unités d’en-tête sont plus lentes que l’importation d’un module nommé.

Les unités d’en-tête ne sont pas affectées par les définitions de macro, sauf si elles sont spécifiées sur la ligne de commande lorsque l’unité d’en-tête est intégrée, ce qui les rend plus robustes que les fichiers d’en-tête.

Les unités d’en-tête exposent les macros et l’implémentation interne définies dans celles-ci comme le font les fichiers d’en-tête, ce qui n’est pas le cas des modules nommés.

Comme une approximation approximative de la taille du fichier, un fichier PCH de 250 mégaoctets peut être représenté par un fichier d’unité d’en-tête de 80 mégaoctets.
Modules Il s’agit du moyen le plus rapide et le plus robuste d’importer des fonctionnalités.

La prise en charge de l’importation de modules a été introduite dans C++20. La bibliothèque standard C++23 présente les deux modules nommés décrits dans cette rubrique.

Lorsque vous importez std, vous obtenez les noms standard tels que std::vector, std::coutmais pas d’extensions, pas d’assistance interne telles que _Sort_unchecked, et pas de macros.

L’ordre des importations n’a pas d’importance, car il n’y a pas de macro ou d’autres effets secondaires.

Comme une approximation approximative de la taille du fichier, un fichier PCH de 250 mégaoctets peut être représenté par un fichier d’unité d’en-tête de 80 mégaoctets, qui peut être représenté par un module de 25 mégaoctets.

Les modules nommés sont plus rapides, car lorsqu’un module nommé est compilé dans un .ifc fichier et un .obj fichier, le compilateur émet une représentation structurée du code source qui peut être chargée rapidement lorsque le module est importé. Le compilateur peut effectuer un certain travail (comme la résolution de noms) avant d’émettre le .ifc fichier en raison de la façon dont les modules nommés sont indépendants de l’ordre et indépendant des macros. Ce travail n’a donc pas à être effectué lorsque le module est importé. En revanche, lorsqu’un fichier d’en-tête est consommé avec #include, son contenu doit être prétraité et compilé à nouveau dans chaque unité de traduction.

Les en-têtes précompilés, qui sont des instantané de mémoire du compilateur, peuvent atténuer ces coûts, mais pas aussi bien que les modules nommés.

Si vous pouvez utiliser les fonctionnalités C++20 et la bibliothèque standard C++23 dans votre application, utilisez des modules nommés.

Si vous pouvez utiliser les fonctionnalités C++20, mais que vous souhaitez passer au fil du temps aux modules, utilisez les unités d’en-tête dans l’intervalle.

Si vous ne pouvez pas utiliser les fonctionnalités C++20, utilisez #include et envisagez des en-têtes précompilés.

Voir aussi

Fichiers d’en-tête précompilés
Vue d’ensemble des modules en C++
Tutoriel : Importer la bibliothèque standard C++ à l’aide de modules
Procédure pas à pas : Importer des bibliothèques STL en tant qu’unités d’en-tête
Procédure pas à pas : Générer et importer des unités d’en-tête dans vos projets Visual C++