J'ai lu qu'il y a une certaine optimisation du compilateur lors de l'utilisation, #pragma once
ce qui peut entraîner une compilation plus rapide. Je reconnais que ce n'est pas standard et pourrait donc poser un problème de compatibilité entre plates-formes.
Est-ce quelque chose qui est pris en charge par la plupart des compilateurs modernes sur les plates-formes non Windows (GCC)?
Je veux éviter les problèmes de compilation de la plate-forme, mais je veux aussi éviter le travail supplémentaire des gardes de secours:
#pragma once
#ifndef HEADER_H
#define HEADER_H
...
#endif // HEADER_H
Dois-je m'inquiéter? Dois-je y consacrer plus d'énergie mentale?
c++
include-guards
Ryan Emerle
la source
la source
#pragma once
semblait éviter certains problèmes d'affichage de classe dans VS 2008. Je suis en train de me débarrasser des gardes d'inclusion et de les remplacer tous#pragma once
pour cette raison.Réponses:
L'utilisation
#pragma once
devrait fonctionner sur n'importe quel compilateur moderne, mais je ne vois aucune raison de ne pas utiliser un standard#ifndef
include guard. Cela fonctionne très bien. La seule mise en garde est que GCC ne prenait pas en charge#pragma once
avant la version 3.4 .J'ai également constaté qu'au moins sur GCC, il reconnaît la
#ifndef
protection standard incluse et l'optimise , donc il ne devrait pas être beaucoup plus lent que#pragma once
.la source
#pragma once
est généralement plus rapide car le fichier n'est pas prétraité.ifndef/define/endif
nécessite un prétraitement de toute façon, car après ce bloc, vous pouvez avoir quelque chose de compilable (théoriquement)#ifndef FOO_BAR_H
, normalement pour un fichier tel que "foo_bar.h". Si vous renommez ce fichier ultérieurement, devez-vous ajuster les protections d'inclusion en conséquence pour être cohérent avec cette convention? De plus, si vous avez deux foo_bar.h distincts à deux endroits différents dans votre arborescence de code, vous devez penser à deux symboles différents pour chacun. La réponse courte est d'utiliser#pragma once
et si vous avez vraiment besoin de compiler dans un environnement qui ne le prend pas en charge, alors allez-y et ajoutez des gardes d'inclusion pour cet environnement.#pragma once
a un inconvénient (autre que d'être non standard) et c'est si vous avez le même fichier à différents emplacements (nous l'avons parce que notre système de construction copie les fichiers), alors le compilateur pensera que ce sont des fichiers différents.la source
#ifdef
valeur de la macro peut également différer.Je souhaite
#pragma once
(ou quelque chose comme ça) avait été dans la norme. Inclure les gardes n'est pas vraiment un gros problème (mais ils semblent être un peu difficiles à expliquer aux personnes qui apprennent la langue), mais cela semble être une gêne mineure qui aurait pu être évitée.En fait, depuis 99,98% du temps, le
#pragma once
comportement est le comportement souhaité, cela aurait été bien si empêcher l'inclusion multiple d'un en-tête était automatiquement géré par le compilateur, avec un#pragma
ou quelque chose pour permettre la double inclusion.Mais nous avons ce que nous avons (sauf que vous pourriez ne pas en avoir
#pragma once
).la source
#import
directive standard .Je ne connais aucun avantage en termes de performances, mais cela fonctionne certainement. Je l'utilise dans tous mes projets C ++ (à condition que j'utilise le compilateur MS). Je trouve que c'est plus efficace que d'utiliser
Il fait le même travail et ne remplit pas le préprocesseur avec des macros supplémentaires.
GCC prend
#pragma once
officiellement en charge à partir de la version 3.4 .la source
GCC prend en charge
#pragma once
depuis la 3.4, voir http://en.wikipedia.org/wiki/Pragma_once pour plus de prise en charge du compilateur.Le gros avantage que je vois sur l'utilisation
#pragma once
plutôt que d'inclure des gardes est d'éviter les erreurs de copier / coller.Avouons-le: la plupart d'entre nous commencent à peine un nouveau fichier d'en-tête à partir de zéro, mais plutôt copions simplement un fichier existant et modifiez-le selon nos besoins. Il est beaucoup plus facile de créer un modèle de travail en utilisant
#pragma once
au lieu d'inclure des gardes. Moins je dois modifier le modèle, moins je risque de rencontrer des erreurs. Avoir le même garde d'inclusion dans différents fichiers conduit à d'étranges erreurs de compilation et il faut un certain temps pour comprendre ce qui n'a pas fonctionné.TL; DR:
#pragma once
est plus facile à utiliser.la source
Je l'utilise et j'en suis content, car je dois taper beaucoup moins pour faire un nouvel en-tête. Cela a bien fonctionné pour moi sur trois plates-formes: Windows, Mac et Linux.
Je n'ai pas d'informations sur les performances mais je pense que la différence entre #pragma et include guard ne sera rien comparée à la lenteur de l'analyse de la grammaire C ++. Voilà le vrai problème. Essayez de compiler le même nombre de fichiers et de lignes avec un compilateur C # par exemple, pour voir la différence.
En fin de compte, utiliser la garde ou le pragma n'aura aucune importance.
la source
L'utilisation de '
#pragma once
' pourrait ne pas avoir d'effet (elle n'est pas prise en charge partout - bien qu'elle soit de plus en plus largement prise en charge), vous devez donc utiliser le code de compilation conditionnelle de toute façon, dans ce cas, pourquoi s'embêter avec '#pragma once
'? Le compilateur l'optimise probablement de toute façon. Cela dépend cependant de vos plateformes cibles. Si toutes vos cibles le prennent en charge, alors allez-y et utilisez-le - mais cela devrait être une décision consciente car tout l'enfer se déchaînera si vous utilisez uniquement le pragma, puis portez sur un compilateur qui ne le prend pas en charge.la source
L'avantage en termes de performances est de ne pas avoir à rouvrir le fichier une fois la #pragma lue. Avec les gardes, le compilateur doit ouvrir le fichier (qui peut être coûteux en temps) pour obtenir les informations qu'il ne devrait plus inclure son contenu.
C'est de la théorie uniquement parce que certains compilateurs n'ouvriront pas automatiquement les fichiers sans code de lecture pour chaque unité de compilation.
Quoi qu'il en soit, ce n'est pas le cas pour tous les compilateurs, donc idéalement, #pragma doit être évité une fois pour le code multiplateforme s'il n'est pas standard du tout / n'a pas de définition et d'effet normalisés. Cependant, pratiquement, c'est vraiment mieux que les gardes.
En fin de compte, la meilleure suggestion que vous pouvez obtenir pour être sûr d'avoir la meilleure vitesse de votre compilateur sans avoir à vérifier le comportement de chaque compilateur dans ce cas, est d'utiliser à la fois pragma et gardes.
De cette façon, vous obtenez le meilleur des deux (multiplateforme et vitesse de compilation de l'aide).
Comme il est plus long à taper, j'utilise personnellement un outil pour aider à générer tout cela de manière très mèche (Visual Assist X).
la source
pragma
after theifndef
? Y a-t-il un avantage?Pas toujours.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 a un bel exemple de deux fichiers destinés à être inclus, mais pensés à tort comme étant identiques en raison d'horodatages et de contenu identiques (nom de fichier différent) .
la source
#pragma once
n'est pas standard, donc tout ce qu'un compilateur décide de faire est "correct". Bien sûr, nous pouvons alors commencer à parler de ce qui est "attendu" et de ce qui est "utile".En utilisant gcc 3.4 et 4.1 sur de très grands arbres (en utilisant parfois distcc ), je n'ai pas encore vu d'accélération lors de l'utilisation de #pragma une fois à la place ou en combinaison avec les gardes d'inclusion standard.
Je ne vois vraiment pas comment cela vaut la peine de confondre les anciennes versions de gcc, ou même d'autres compilateurs, car il n'y a pas de réelles économies. Je n'ai pas essayé tous les différents dé-linters, mais je suis prêt à parier que cela en confondra beaucoup.
Je souhaite moi aussi qu'il ait été adopté dès le début, mais je peux voir l'argument "Pourquoi en avons-nous besoin si ifndef fonctionne parfaitement bien?". Compte tenu des nombreux coins sombres et de la complexité de C, les gardes d'inclusion sont l'une des choses les plus faciles à expliquer. Si vous avez même une petite connaissance du fonctionnement du préprocesseur, ils devraient être explicites.
Cependant, si vous observez une accélération importante, veuillez mettre à jour votre question.
la source
Aujourd'hui, les gardes à l'ancienne sont aussi rapides qu'une #pragma une fois. Même si le compilateur ne les traite pas spécialement, il s'arrêtera quand il verra #ifndef WHATEVER et WHATEVER est défini. L'ouverture d'un fichier est très bon marché aujourd'hui. Même s'il devait y avoir une amélioration, ce serait de l'ordre des millisecondes.
Je n'utilise tout simplement pas #pragma une fois, car cela n'a aucun avantage. Pour éviter les conflits avec d'autres gardes d'inclusion, j'utilise quelque chose comme: CI_APP_MODULE_FILE_H -> CI = Company Initials; APP = nom de l'application; Le reste est explicite.
la source
La principale différence est que le compilateur a dû ouvrir le fichier d'en-tête pour lire le garde d'inclusion. En comparaison, pragma oblige le compilateur à garder une trace du fichier et à ne faire aucun IO de fichier lorsqu'il rencontre une autre inclusion pour le même fichier. Bien que cela puisse sembler négligeable, il peut facilement évoluer avec d'énormes projets, en particulier ceux sans bon en-tête.
Cela dit, de nos jours, les compilateurs (y compris GCC) sont assez intelligents pour traiter une fois les gardes comme Pragma. c'est-à-dire qu'ils n'ouvrent pas le fichier et évitent la pénalité d'E / S du fichier.
Dans les compilateurs qui ne prennent pas en charge pragma, j'ai vu des implémentations manuelles un peu lourdes.
Personnellement, j'aime l'approche #pragma une fois car elle évite les tracas de nommer les collisions et les erreurs de frappe potentielles. C'est aussi un code plus élégant en comparaison. Cela dit, pour le code portable, cela ne devrait pas faire de mal d'avoir les deux à moins que le compilateur ne s'en plaint.
la source
#pragma once
qui existait!Si nous utilisons msvc ou Qt (jusqu'à Qt 4.5), depuis GCC (jusqu'à 3.4), msvc supporte tous les deux
#pragma once
, je ne vois aucune raison de ne pas l'utiliser#pragma once
.Le nom du fichier source est généralement le même nom de classe égal, et nous savons, parfois, nous avons besoin d'un remaniement , pour renommer le nom de la classe, alors nous avons dû changer le
#include XXXX
aussi, donc je pense que le maintien manuel#include xxxxx
n'est pas un travail intelligent. même avec l'extension Visual Assist X, maintenir le "xxxx" n'est pas un travail nécessaire.la source
Note supplémentaire aux personnes qui pensent qu'une inclusion automatique unique des fichiers d'en-tête est toujours souhaitée: je construis des générateurs de code en utilisant une double ou plusieurs inclusion de fichiers d'en-tête depuis des décennies. Surtout pour la génération de stubs de bibliothèque de protocoles, je trouve très confortable d'avoir un générateur de code extrêmement portable et puissant sans outils et langages supplémentaires. Je ne suis pas le seul développeur à utiliser ce schéma comme le montrent ces blogs X-Macros . Cela ne serait pas possible sans le gardiennage automatique manquant.
la source
X-Macro
fonctionnalité, mais ce n'est pas l'utilisation principale d'inclure, ne devrait-il pas être l'inverse comme header unguard / # pragma multi si nous devions rester avec DRY?