73 votes

L'utilisation de double include gardes en C ++

Donc, j'ai récemment eu une discussion où je travaille, où je doute de l'utilisation d'un double inclure la garde dans un seul garde. Ce que je veux dire par double garde est comme suit:

Fichier d'en-tête, "header_a.hpp":

#ifndef __HEADER_A_HPP__
#define __HEADER_A_HPP__
...
...
#endif

Lors de l'inclusion du fichier d'en-tête de n'importe où, que ce soit dans un en-tête ou le fichier source:

#ifndef __HEADER_A_HPP__
#include "header_a.hpp"
#endif

Maintenant, je comprends que l'utilisation de la garde dans les fichiers d'en-tête est pour éviter que plusieurs inclusion d'un déjà défini fichier d'en-tête, il est courant et bien documenté. Si la macro est déjà défini, l'ensemble de l'en-tête de fichier est vu comme "blanc" par le compilateur et la double inclusion est empêché. Assez Simple.

La question que je ne comprends pas, c'est à l'aide de #ifndef __HEADER_A_HPP__ et #endif autour de la #include "header_a.hpp". Je suis informé par le collègue de travail que cela ajoute une seconde couche de protection pour les inclusions, mais je ne vois pas comment cette seconde couche est même utile si la première couche ne fait absolument le travail (ou si?).

Le seul avantage que je peux venir avec, c'est qu'il s'arrête carrément l'éditeur de liens de déranger pour trouver le fichier. Est-ce censé améliorer le temps de compilation (qui n'a pas été mentionné comme un avantage), ou est-il autre chose ici que je ne suis pas le voir?

107voto

Edgar Rokyan Points 1335

Je suis assez sûr que c'est une mauvaise pratique pour ajouter un autre inclure garde comme:

#ifndef __HEADER_A_HPP__
#include "header_a.hpp"
#endif

Voici quelques raisons pour lesquelles:

  1. Pour éviter la double inclusion, il suffit d'ajouter une habitude inclure garde à l'intérieur de l'en-tête de fichier lui-même. Il fait bien le travail. Une autre mesure prévoit de garde à la place de l'inclusion juste mess le code et réduit la lisibilité.

  2. Il ajoute inutilement dépendances. Si vous le changement de la garde à l'intérieur de l'en-tête de fichier que vous avez à changer dans tous les lieux où l'en-tête est inclus.

  3. Ce n'est certainement pas le plus cher de l'opération de comparaison de l'ensemble de la compilation ou le couplage des processus de sorte qu'il peut difficilement réduire le total de la construction.

  4. Quel que soit le compilateur vaut rien déjà optimise les fichiers comportent-gardes.

51voto

Pete Becker Points 27371

La raison pour mettre inclure des gardes dans l' en-tête de fichier est d'empêcher le contenu de l'en-tête d'être tiré dans une unité de traduction, plus d'une fois. C'est normal, pratique établie de longue date.

La raison pour mettre redondant inclure les gardiens d'une source de fichier est pour éviter d'avoir à ouvrir le fichier d'en-tête est inclus, et de retour dans les temps anciens qui pourraient augmenter la vitesse de compilation. Ces jours-ci, l'ouverture d'un fichier est beaucoup plus rapide qu'elle ne l'habitude d'être; de plus, les compilateurs sont assez intelligents de se souvenir de qui fichiers qu'ils ont déjà vu, et qu'ils comprennent les inclure garde idiome, donc, peuvent trouver leur propre qu'ils n'ont pas besoin de l'ouvrir à nouveau le fichier. C'est un peu de la main-saluer de la main, mais la ligne de fond est que cette couche supplémentaire n'est pas nécessaire non plus.

EDIT: un autre facteur est que la compilation C++ est beaucoup plus compliqué que la compilation de C, de sorte qu'il prend beaucoup plus de temps, ce qui rend le temps passé à l'ouverture de fichiers à inclure un plus petit, moins importante partie du temps qu'il faut pour compiler une unité de traduction.

22voto

user2079303 Points 4916

Le seul avantage que je peux venir avec, c'est qu'il s'arrête carrément l'éditeur de liens de déranger pour trouver le fichier.

L'éditeur de liens ne sera pas affecté en aucune façon.

Elle pourrait empêcher le pré-processeur de s'embêter à trouver le fichier, mais si la protection est définie, ce qui signifie qu'il a déjà trouvé le fichier. Je pense que si le temps est réduit à tous, l'effet serait tout à fait minime, sauf dans les plus pathologiquement récursivement inclus monstruosité.

Il a un inconvénient est que si la garde est jamais modifié (par exemple suite à un conflit avec un autre gardien), toutes les conditions avant de l'inclure des directives doivent être modifiés afin pour eux de travailler. Et si quelque chose d'autre utilise le précédent de la garde, puis les conditions doivent être modifiés pour inclure la directive elle-même fonctionner correctement.

P. S. __HEADER_A_HPP__ est un symbole qui est réservé à la mise en œuvre, de sorte qu'il n'est pas quelque chose que vous pouvez définir. Utiliser un autre nom pour la garde.

17voto

Muzer Points 224

Les compilateurs plus âgés sur les plus traditionnelles (mainframe) plates-formes (nous parlons milieu des années 2000 ici) n'a pas l'habitude d'avoir l'optimisation décrites dans d'autres réponses, et donc il a vraiment utilisé pour ralentir significativement temps de prétraitement d'avoir à re-lire l'en-tête des fichiers qui ont déjà été inclus (en gardant à l'esprit dans une grande, monolithique, l'entreprise y projet que vous allez être y compris un grand nombre de fichiers d'en-tête). Comme un exemple, j'ai vu des données qui indiquent que 26 fois speedup pour un fichier avec 256 fichiers d'en-tête comprenant chacun les mêmes 256 fichiers d'en-tête sur la VisualAge C++ 6 pour AIX compilateur (qui date du milieu des années 2000). C'est plutôt un exemple extrême, mais ce genre de speed-up ajoute.

Cependant, tous les compilateurs modernes, même sur des gros des plates-formes telles qu'AIX et Solaris, effectuer suffisamment d'optimisation de la pour en-tête d'inclusion à la différence de ces jours-ci est vraiment négligeable. Par conséquent, il n'y a pas de bonne raison d'avoir ces plus.

Il ne s'agit, toutefois, d'expliquer pourquoi certaines entreprises continuent de s'accrocher à la pratique, parce que relativement récemment (au moins en C/C++ code de base à l'âge), il est toujours intéressant pour les très grandes monolithique projets.

8voto

Bert Bril Points 322

Bien qu'il existe des personnes faisant valoir contre elle, en pratique "#pragma once " fonctionne parfaitement et les principaux compilateurs (gcc/g++, vc++) en charge.

Donc quel que soit le puriste de l'argumentation de personnes sont étalés, ça fonctionne beaucoup mieux:

  1. Rapide
  2. Pas d'entretien, pas de problèmes avec la mystérieuse non-inclusion parce que vous avez copié un vieux drapeau
  3. Seule ligne avec la signification évidente contre énigmatiques lignes de propagation dans le fichier

Donc il suffit de mettre:

#pragma once

au début du fichier, et c'est tout. Optimisé, maintenable, et prêt à aller.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X