Je suis en train de passer par Contrôle de comportement défini par l'implémentation
et il y a le texte suivant en relation avec #pragma once
:
Contrairement aux protections d'en-tête, ce pragma rend impossible l'utilisation erronée du même nom de macro dans plus d'un fichier.
Je ne suis pas sûr de ce que cela implique. Quelqu'un peut-il expliquer?
TIA
3 Réponses :
Exemple :
// /usr/include/lib.h #pragma once struct foo{}; // src/ext/lib.h #pragma once struct foo{}; // src/headerA.h #pragma once #include <lib.h> // src/headerB.h #pragma once #include "ext/lib.h" // src/file.cpp #include "headerA.h" #include "headerB.h" // oops, lib.h is include twice foo f;
Les macros de garde d'en-tête nécessitent un effort méticuleux pour les garder uniques. #pragma once
fait cela automatiquement.
Pour être honnête et pour être complet, permettez-moi de mentionner l'inconvénient (également dans la page liée): #pragma once
ne reconnaît pas le même fichier s'il est inclus à partir de plusieurs chemins. Cela peut être un problème pour les projets avec une structure de fichiers exotique. Exemple:
// src/featureA/thingy.h #ifndef HEADER_GUARD_FOR_THINGY #define HEADER_GUARD_FOR_THINGY struct foo{}; #endif // src/featureB/thingy.h #ifndef HEADER_GUARD_FOR_THINGY #define HEADER_GUARD_FOR_THINGY struct bar{}; #endif // src/file.cpp #include "featureA/thingy.h" #include "featureB/thingy.h" // oops, this file is removed by header guard foo f; bar b;
Bien que tout cela soit correct, cela ne mentionne pas les problèmes rencontrés par #pragma once
qui n'existent pas avec les gardes d'inclusion.
@PeteBecker ce n'est pas ce qui a été demandé. Mais je l'ai maintenant ajouté par souci d'exhaustivité.
Disons que vous avez un fichier d'en-tête, File1.h. Vous avez créé File1.h avec:
#pragma once
Il n'y a rien dans la langue pour empêcher d'autres fichiers d'en-tête d'utiliser la même macro, FILE_1_H
, comme include gardes. p>
Lorsque cela se produit, un seul des fichiers .h peut être #include
d dans un fichier .cpp. Dans le meilleur des cas, vous obtiendrez des erreurs de compilation qui permettront de résoudre le problème. Dans le pire des cas, vous finirez par utiliser le mauvais type ou la mauvaise fonction et le problème se manifestera au moment de l'exécution.
Pour ces raisons, les protections d'inclusion ne sont pas robustes et sujettes à des erreurs de l'utilisateur.
Cependant, si votre compilateur le prend en charge et que vous utilisez
#pragma once
dans tous vos fichiers d'en-tête, de telles erreurs seront évitées.
Veuillez noter que l'utilisation de
#ifndef FILE_1_H #define FILE_1_H // Contents of File1.h #endif
a ses propres inconvénients. Pour en savoir plus, consultez ce qui suit:
Est #pragma autrefois un garde d'inclusion sûr?
Quels sont les dangers d'utiliser #pragma une fois? p>
Bien que tout cela soit correct, cela ne mentionne pas les problèmes rencontrés par #pragma once
qui n'existent pas avec les gardes d'inclusion.
@PeteBecker, c'est vrai. Elle est cependant orthogonale à la question du PO.
Inclure les gardes ressemblent à ceci:
#ifndef SOME_NAME #define SOME_NAME // The header file contents #endif
Bien qu'il y ait des conventions de dénomination, il n'y a rien pour imposer ce que la macro ( SOME_NAME
dans ce cas) sera réellement appelée . Si vous essayez d'inclure deux fichiers d'en-tête qui utilisent le même nom de macro, le compilateur ne verra pas le contenu du deuxième fichier car #ifndef ___
de ce fichier échouera (la macro était déjà définie dans le premier fichier).
Ce problème n'existe pas avec #pragma once
.
Bien que tout cela soit correct, cela ne mentionne pas les problèmes rencontrés par #pragma once
qui n'existent pas avec les gardes d'inclusion.
@PeteBecker Je répondais à la question dans l'OP, qui était une explication de la citation.
Oui, mais vous n’avez pas mentionné que la citation est trompeuse.
@PeteBecker Je ne vois pas en quoi c'est trompeur. Cela explique un inconvénient des protections d'en-tête que #pragma once
n'a pas. La phrase suivante de la citation explique les inconvénients de #pragma once
: "D'un autre côté, puisque avec #pragma once
les fichiers sont exclus en fonction de leur système de fichiers- identité de niveau, cela ne peut pas empêcher d'inclure un en-tête deux fois s'il existe à plus d'un emplacement dans un projet. "
Cela implique que vous pouvez utiliser la même macro comme garde dans différents fichiers par erreur
Notez que
#pragma once
a des failles qui peuvent être exposées par une structure de projet modérément compliquée.@ user4581301 - en effet. C’est pourquoi
#pragma once
ne fait pas partie du C standard ou du C ++ standard.Vous voudrez peut-être vous pencher sur cette question: stackoverflow.com/ questions / 1143936 /…