Hypothèses
L'un des avantages des bibliothèques d'en-tête uniquement pour C++ est qu'elles n'ont pas besoin d'être compilées séparément.
En C et C++ inline
n'a de sens que si la fonction est définie dans un fichier d'en-tête *.
Traditionnellement, en C, la disposition .c/.h a été utilisée, où l'en-tête représente l'interface publique minimale de l'unité de traduction. De même, .cpp/hpp.
Question
Les bibliothèques uniquement en-tête sont-elles généralement plus efficaces en termes de code et de temps d'exécution que la mise en page traditionnelle? Si tel est le cas, est-ce dû à une intégration importante ou à d'autres optimisations?
* - la définition de la fonction dans un en-tête permet au compilateur de voir l'implémentation pendant la compilation de n'importe quelle unité de traduction et rend pratiquement possible le code en ligne
L'un des avantages des bibliothèques d'en-tête uniquement pour C++ est qu'elles n'ont pas besoin d'être compilées séparément
Non, ce n'est pas un avantage, bien au contraire - la partie principale de la bibliothèque doit être compilée aussi souvent qu'elle est incluse, pas seulement une fois. Cela augmentera généralement les temps de compilation. Cependant, si vous faites référence aux avantages énumérés ici dans Wikipedia : cet article parle d'une réduction des frais administratifs liés à l'ensemble du processus de construction, d'empaquetage et de déploiement.
En C et C++ inline n'a de sens que si la fonction est définie dans un fichier d'en-tête *
Cela dépend du système du compilateur/éditeur de liens, mais je suppose que pour la plupart des compilateurs C et C++ existants, cela est vrai.
Traditionnellement, en C, la disposition .c/.h a été utilisée, où l'en-tête représente l'interface publique minimale de l'unité de traduction. De même, .cpp/hpp.
C'est surtout correct. Les en-têtes de classe C++ contiennent souvent plus que l'interface publique minimale - ils contiennent généralement aussi beaucoup de choses privées. Pour atténuer cela, des choses comme le idiome PIMPL sont utilisées. C'est quelque chose comme "l'opposé" d'une bibliothèque uniquement en-tête, il essaie de minimiser le contenu d'en-tête nécessaire.
Mais pour répondre à votre question principale: c'est un compromis. Plus on met de code de bibliothèque dans les fichiers d'en-tête, plus le compilateur a une chance d'optimiser le code pour la vitesse (si cela se produit vraiment, ou si l'augmentation est notable, est une question complètement différente). D'un autre côté, trop de code dans les en-têtes augmente le temps de compilation. Surtout dans les grands projets C++, cela peut devenir un problème grave, voir "Large Scale C++ Software Design" par John Lakos - bien que le livre soit un peu dépassé et que certains des problèmes décrits ici soient résolus par compilateurs modernes, les idées/solutions générales sont toujours valables.
En particulier, lorsque vous n'utilisez pas une bibliothèque stable (tierce), mais que vous développez vos propres bibliothèques pendant votre projet, les temps de compilation deviennent apparents. Chaque fois que vous changez quelque chose dans la bibliothèque, vous devez changer un fichier d'en-tête, ce qui provoquera une recompilation et une liaison de toutes les unités dépendantes.
À mon humble avis, la popularité des bibliothèques uniquement en-tête est causée par la popularité de la méta-programmation de modèles. Pour la plupart des compilateurs, les bibliothèques basées sur des modèles doivent être uniquement en-tête car le compilateur ne peut démarrer le processus de compilation principal que lorsque les paramètres de type sont fournis, et pour une compilation et une optimisation complètes, le compilateur doit voir "les deux à once "- le code de la bibliothèque plus les valeurs des paramètres du modèle. Cela rend impossible (ou du moins difficile) de produire des unités de compilation "précompilées" pour une telle bibliothèque.
Eh bien, démolissons d'abord certaines de vos hypothèses:
- L'un des avantages des bibliothèques d'en-tête uniquement pour C++ est qu'elles n'ont pas besoin d'être compilées séparément.
Compiler les choses séparément signifie potentiellement ne pas avoir à tout recompiler si seulement une partie change.
Donc, un désavantage au lieu d'un avantage.
- En C et C++ inline n'a de sens que si la fonction est définie dans un fichier d'en-tête *.
Oui, le seul effet que inline
a laissé est l'exception à la règle d'une définition .
Malheur à vous si ces définitions diffèrent de quelque façon que ce soit.
Donc, si une fonction est interne à une unité de compilation, marquez-la static
. Cela rend également l'inline plus probable, car la fonction doit être disponible afin de l'intégrer.
Encore, jetez un œil à l'optimisation du temps de liaison, telle que prise en charge par au moins MSVC++, gcc et clang.
- Traditionnellement, en C, la disposition .c/.h a été utilisée, où l'en-tête représente l'interface publique minimale de l'unité de traduction. De même, .cpp/hpp.
Eh bien, ne présenter que l'interface minimale est certainement l'un des objectifs, pour obtenir une stabilité API et ABI plus élevée, et pour minimiser les temps de compilation.
En particulier, les classes C++ ne sont pas vraiment adaptées à cela, car tous les bits privés fuient dans l'en-tête, tout comme les bits protégés, que vous en dériviez ou non.
Le motif de conception PIMPL sert à réduire ces détails.
La partie où la séparation de l'interface et de l'implémentation échoue complètement en C++ est les modèles.
Le comité a essayé de faire quelque chose avec modèles exportés , mais cela a été abandonné car trop compliqué et ne fonctionnant pas vraiment.
Maintenant, ils travaillent sur n système de modules approprié , bien que cela soit lent. Cela réduit considérablement les temps de compilation et devrait également augmenter la stabilité de l'API et de l'ABI en diminuant leur surface.
Les bibliothèques uniquement en-tête sont-elles généralement plus efficaces en termes de code et de temps d'exécution que la mise en page traditionnelle? Si tel est le cas, est-ce dû à une intégration importante ou à d'autres optimisations?
Les bibliothèques d'en-tête uniquement peuvent être plus efficaces en termes de taille de code et de temps d'exécution, bien que cela dépende du fait que la bibliothèque soit partagée, de la quantité utilisée, de quelles manières et si l'incrustation s'avère une victoire décisive dans ce cas spécifique.
Et la raison pour laquelle l'inline est si importante pour l'optimisation n'est pas parce que l'inline elle-même est un formidable coup de pouce, mais en raison des possibilités de propagation constante et d'optimisation supplémentaire qu'elle ouvre.