Plusieurs raisons
Fichiers d'en-tête
Chaque unité de compilation nécessite des centaines, voire des milliers, d'en-têtes à (1) charger et (2) compiler. Chacun d'entre eux doit généralement être recompilé pour chaque unité de compilation, car le préprocesseur s'assure que le résultat de la compilation d'un en-tête pourrait varient entre chaque unité de compilation. (Une macro peut être définie dans une unité de compilation qui modifie le contenu de l'en-tête).
C'est probablement le site raison principale, car il faut compiler d'énormes quantités de code pour chaque unité de compilation, et de plus, chaque en-tête doit être compilé plusieurs fois. (une fois pour chaque unité de compilation qui l'inclut).
Lien vers
Une fois compilés, tous les fichiers objets doivent être liés entre eux. Il s'agit d'un processus monolithique qui ne peut pas vraiment être parallélisé et qui doit traiter l'ensemble de votre projet.
Analyse syntaxique
La syntaxe est extrêmement compliquée à analyser, dépend fortement du contexte et est très difficile à désambiguïser. Cela prend beaucoup de temps.
Modèles
En C#, List<T>
est le seul type qui est compilé, quel que soit le nombre d'instanciations de List que vous avez dans votre programme. En C++, vector<int>
est un type complètement distinct de vector<float>
et chacune d'entre elles devra être compilée séparément.
Ajoutez à cela que les modèles constituent un "sous-langage" complet de Turing que le compilateur doit interpréter, et cela peut devenir ridiculement compliqué. Même un code de métaprogrammation de modèles relativement simple peut définir des modèles récursifs qui créent des dizaines et des dizaines d'instanciations de modèles. Les modèles peuvent également donner lieu à des types extrêmement complexes, avec des noms ridiculement longs, ce qui ajoute beaucoup de travail supplémentaire à l'éditeur de liens. (Il doit comparer un grand nombre de noms de symboles, et si ces noms peuvent atteindre plusieurs milliers de caractères, cela peut devenir assez coûteux).
Et bien sûr, ils exacerbent les problèmes liés aux fichiers d'en-tête, car les modèles doivent généralement être définis dans les en-têtes, ce qui signifie que beaucoup plus de code doit être analysé et compilé pour chaque unité de compilation. Dans le code C ordinaire, un en-tête ne contient généralement que des déclarations prospectives, mais très peu de code réel. En C++, il n'est pas rare que la quasi-totalité du code réside dans les fichiers d'en-tête.
Optimisation
Le C++ permet des optimisations très importantes. Le C# ou Java ne permettent pas d'éliminer complètement les classes (elles doivent être présentes à des fins de réflexion), mais même un simple métaprogramme de modèles C++ peut facilement générer des dizaines ou des centaines de classes, qui sont toutes intégrées et éliminées lors de la phase d'optimisation.
En outre, un programme C++ doit être entièrement optimisé par le compilateur. Un programme C# peut compter sur le compilateur JIT pour effectuer des optimisations supplémentaires au moment du chargement, Le C++ n'a pas de telles "secondes chances". Ce que le compilateur génère est aussi optimisé que possible.
Machine
Le C++ est compilé en code machine qui peut être un peu plus compliqué que le bytecode utilisé par Java ou .NET (surtout dans le cas de x86). (Ce point est mentionné par souci d'exhaustivité uniquement parce qu'il a été mentionné dans des commentaires et autres. En pratique, il est peu probable que cette étape prenne plus qu'une infime partie du temps total de compilation).
Conclusion
La plupart de ces facteurs sont partagés par le code C, qui se compile d'ailleurs assez efficacement. L'étape d'analyse syntaxique est beaucoup plus compliquée en C++, et peut prendre beaucoup plus de temps, mais le principal coupable est probablement les modèles. Ils sont utiles et font du C++ un langage beaucoup plus puissant, mais ils ont aussi un impact négatif sur la vitesse de compilation.
62 votes
VC++ supporte les en-têtes précompilés. Les utiliser vous aidera. Beaucoup.
1 votes
Oui, dans mon cas (principalement C avec quelques classes - pas de templates), les en-têtes précompilés accélèrent d'environ 10x.
0 votes
@Brian Je n'utiliserais jamais une tête pré-compilée dans une bibliothèque.
0 votes
Essayez TinyCC, cependant, il est juste optimisé TRÈS peu
1 votes
Vous pouvez utiliser des en-têtes pré-compilés et du code C++. Lorsque vous compilez votre code, il ne met à jour que les fichiers contenant des modifications. Cette opération prend très peu de temps. Recompiler un projet entier peut prendre 10 fois plus de temps.
18 votes
It takes significantly longer to compile a C++ file
- Voulez-vous dire 2 secondes par rapport à 1 seconde ? Certes, c'est deux fois plus long, mais ce n'est guère significatif. Ou bien voulez-vous dire 10 minutes par rapport à 5 secondes ? Veuillez quantifier.1 votes
OT : utilisation ccache pour accélérer :-)
0 votes
#pragma once
2 votes
Je parie sur les modules ; je ne m'attends pas à ce que les projets C++ deviennent plus rapides à construire que les autres langages de programmation juste avec des modules, mais cela peut être très proche pour la plupart des projets avec une certaine gestion. J'espère voir un bon gestionnaire de paquets avec l'intégration d'Artifactory après les modules.
0 votes
J'ai utilisé g++ dans les années 1990 et il était beaucoup plus rapide à l'époque qu'il ne l'est maintenant. Ce devrait être l'inverse. Je suppose qu'il est devenu horriblement gonflé. "g++ (GCC) 7.4.0" vient de prendre 2 minutes pour compiler un programme C++ de 23 lignes qui fait juste des trucs basiques avec des listes ! J'utilise Cygwin g++ sur Windows 10 avec Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz (4 CPUs), ~2.7GHz.
0 votes
NickGammon Eh bien, si la compilation du C++ n'était que deux fois plus longue, on ne pourrait pas qualifier cela de significativement plus long ! D'un autre côté, si c'était 120 fois plus lent, alors personne ne l'utiliserait. C'est plus comme 10 fois plus lent quelque chose comme 10 fichiers par seconde en C# ou 1 par seconde en C++.