it-swarm.com.de

#pragma once vs include guards?

Ich arbeite an einer Codebasis, von der bekannt ist, dass sie nur unter Windows ausgeführt und unter Visual Studio kompiliert werden kann (sie ist eng in Excel integriert, sodass sie nirgendwo hingehen kann). Ich frage mich, ob ich die traditionellen Include-Guards verwenden oder #pragma once Für unseren Code verwenden soll. Ich denke, wenn der Compiler mit #pragma once Arbeitet, werden schnellere Kompilierungen erzielt, und das Kopieren und Einfügen ist weniger fehleranfällig. Es ist auch etwas weniger hässlich ;)

Hinweis: Um die Kompilierungszeiten zu verkürzen, können wir Redundant Include Guards verwenden. Dies sorgt jedoch für eine enge Kopplung zwischen der eingeschlossenen Datei und der eingeschlossenen Datei. Normalerweise ist dies in Ordnung, da der Schutz auf dem Dateinamen basieren sollte und sich nur ändern würde, wenn Sie den Include-Namen trotzdem ändern müssten.

331
Matt Price

Ich denke nicht, dass es einen signifikanten Unterschied in der Kompilierungszeit macht, aber #pragma once wird von allen Compilern sehr gut unterstützt, ist aber nicht Teil des Standards. Der Präprozessor kann etwas schneller damit arbeiten, da es einfacher ist, Ihre genauen Absichten zu verstehen.

#pragma once ist weniger fehleranfällig und es muss weniger Code eingegeben werden.

Um die Kompilierungszeit zu beschleunigen, deklarieren Sie einfach die Weiterleitung, anstatt sie in .h-Dateien einzuschließen, wenn Sie können.

Ich bevorzuge #pragma once.

Siehe diesen Wikipedia-Artikel über die Möglichkeit der Verwendung von beiden .

290
Brian R. Bondy

Ich wollte nur zu dieser Diskussion hinzufügen, dass ich gerade auf VS und GCC kompiliere, und verwendete, um Schutzvorrichtungen einzuschließen. Ich bin jetzt auf #pragma once Umgestiegen, und der einzige Grund für mich ist nicht die Leistung, Portabilität oder der Standard, da es mir eigentlich egal ist, was Standard ist, solange VS und GCC dies unterstützen. Und das ist:

#pragma once Reduziert die Möglichkeit von Fehlern.

Es ist allzu einfach, eine Header-Datei zu kopieren und in eine andere Header-Datei einzufügen, sie an die eigenen Bedürfnisse anzupassen und den Namen des Include-Schutzes zu vergessen. Sobald beide enthalten sind, dauert es eine Weile, bis Sie den Fehler gefunden haben, da die Fehlermeldungen nicht unbedingt klar sind.

160
Cookie

#pragma once hat nicht korrigierbare Fehler. Es sollte niemals verwendet werden.

Wenn Ihr #include Suchpfad ausreichend kompliziert ist, kann der Compiler möglicherweise den Unterschied zwischen zwei Headern mit demselben Basisnamen nicht erkennen (z. B. a/foo.h und b/foo.h). Ein #pragma once in einem von ihnen unterdrückt beide . Möglicherweise kann auch nicht festgestellt werden, dass zwei verschiedene relative Includes (z. B. #include "foo.h" und #include "../a/foo.h" auf dieselbe Datei verweisen, sodass #pragma once ein redundantes Include nicht unterdrücken kann wenn es sein sollte.

Dies wirkt sich auch auf die Fähigkeit des Compilers aus, das erneute Lesen von Dateien mit #ifndef Guards zu vermeiden. Dies ist jedoch nur eine Optimierung. Mit #ifndef guards kann der Compiler jede Datei sicher lesen, die er nicht sicher gesehen hat. Wenn es falsch ist, muss es nur etwas zusätzliche Arbeit leisten. Solange keine zwei Header dasselbe Guard-Makro definieren, wird der Code wie erwartet kompiliert. Und wenn zwei Header dasselbe Guard-Makro definieren , kann der Programmierer einen von ihnen ändern.

#pragma once hat kein solches Sicherheitsnetz - wenn der Compiler bezüglich der Identität einer Header-Datei falsch ist, so oder so das Programm wird nicht kompiliert. Wenn Sie auf diesen Fehler stoßen, haben Sie nur die Möglichkeit, die Verwendung von #pragma once zu beenden oder einen der Header umzubenennen. Die Namen der Header sind Teil Ihres API-Vertrags, daher ist das Umbenennen wahrscheinlich keine Option.

(Die Kurzversion von unfixable ist, dass weder die Unix- noch die Windows-Dateisystem-API einen Mechanismus bieten, der garantiert , dass Sie wissen, ob zwei absolute Pfadnamen auf dieselbe Datei verweisen. Wenn Sie den Eindruck haben, dass dafür Inode-Nummern verwendet werden können, sind Sie falsch.)

(Historischer Hinweis: Der einzige Grund, warum ich #pragma once und #import nicht aus GCC herausgerissen habe, als ich die Berechtigung dazu hatte, ~ vor 12 Jahren, waren Apples System-Header, auf die ich mich verlassen habe Rückblickend hätte mich das nicht aufhalten sollen.)

(Da dies jetzt zweimal im Kommentarthread vorkommt: Die GCC-Entwickler haben sich große Mühe gegeben, #pragma once so zuverlässig wie möglich zu machen; siehe GCC-Fehlerbericht 11569 . Die Implementierung in aktuellen Versionen von GCC kann jedoch unter plausiblen Bedingungen immer noch scheitern, wie z Die Implementierung des Compilers ist ähnlich, aber ich würde nicht erwarten, dass es jemand besser gemacht hätte .)

108
zwol

Bis der Tag #pragma once Zum Standard wird (dies ist derzeit keine Priorität für zukünftige Standards), schlage ich vor, dass Sie ihn verwenden UND Wachen verwenden, und zwar auf folgende Weise:

#ifndef BLAH_H
#define BLAH_H
#pragma once

// ...

#endif

Die Gründe sind:

  • #pragma once Ist kein Standard, daher ist es möglich, dass einige Compiler die Funktionalität nicht bereitstellen. Das heißt, alle großen Compiler unterstützen es. Wenn ein Compiler es nicht weiß, wird es zumindest ignoriert.
  • Da es für #pragma once Kein Standardverhalten gibt, sollten Sie nicht davon ausgehen, dass das Verhalten auf allen Compilern gleich ist. Die Guards stellen zumindest sicher, dass die Grundannahme für alle Compiler gleich ist, die zumindest die erforderlichen Präprozessoranweisungen für Guards implementieren.
  • Bei den meisten Compilern beschleunigt #pragma once Die Kompilierung (von einem CPP), da der Compiler die Datei mit dieser Anweisung nicht erneut öffnet. Je nach Compiler kann es also hilfreich sein, ihn in einer Datei zu haben oder nicht. Ich habe gehört, dass g ++ die gleiche Optimierung durchführen kann, wenn Wachen erkannt werden, dies muss jedoch bestätigt werden.

Wenn Sie die beiden zusammen verwenden, erhalten Sie das Beste aus jedem Compiler.

Wenn Sie kein automatisches Skript zum Generieren der Wachen haben, ist es möglicherweise bequemer, nur #pragma once Zu verwenden. Wissen Sie einfach, was das für tragbaren Code bedeutet. (Ich benutze VAssistX, um die Wachen und das Pragma einmal schnell zu generieren.)

Sie sollten Ihren Code fast immer portabel denken (weil Sie nicht wissen, woraus die Zukunft besteht), aber wenn Sie wirklich denken, dass er nicht mit einem anderen Compiler kompiliert werden soll (z. B. Code für sehr spezielle eingebettete Hardware) Dann sollten Sie einfach in Ihrer Compiler-Dokumentation zu #pragma once nachsehen, was Sie wirklich tun.

35
Klaim

Aus Sicht eines Software-Testers

#pragma once Ist kürzer als ein Include-Guard, weniger fehleranfällig, wird von den meisten Compilern unterstützt, und einige sagen, dass es schneller kompiliert wird (was nicht mehr wahr ist).

Aber ich schlage immer noch vor, Sie gehen mit standardmäßigen #ifndef Schutzvorrichtungen.

Warum #ifndef?

Stellen Sie sich eine künstliche Klassenhierarchie wie diese vor, in der jede der Klassen A, B und C in einer eigenen Datei lebt:

ah

#ifndef A_H
#define A_H

class A {
public:
  // some virtual functions
};

#endif

b.h.

#ifndef B_H
#define B_H

#include "a.h"

class B : public A {
public:
  // some functions
};

#endif

cH

#ifndef C_H
#define C_H

#include "b.h"

class C : public B {
public:
  // some functions
};

#endif

Angenommen, Sie schreiben Tests für Ihre Klassen und müssen das Verhalten der wirklich komplexen Klasse B simulieren. Eine Möglichkeit, dies zu tun, besteht darin, eine Scheinklasse zu schreiben, indem Sie zum Beispiel Google-Schein verwenden und diese in ein Verzeichnis mocks/b.h Einfügen. Beachten Sie, dass sich der Klassenname nicht geändert hat, sondern nur in einem anderen Verzeichnis gespeichert ist. Am wichtigsten ist jedoch, dass der Include-Guard genau so heißt wie in der Originaldatei b.h.

mocks/b.h

#ifndef B_H
#define B_H

#include "a.h"
#include "gmock/gmock.h"

class B : public A {
public:
  // some mocks functions
  MOCK_METHOD0(SomeMethod, void());
};

#endif

Was ist der vorteil

Mit diesem Ansatz können Sie das Verhalten der Klasse B nachahmen, ohne die ursprüngliche Klasse zu berühren oder C darüber zu erzählen. Alles was Sie tun müssen, ist das Verzeichnis mocks/ In den Include-Pfad Ihres Compliers zu schreiben.

Warum geht das nicht mit #pragma once?

Wenn Sie #pragma once Verwendet hätten, würden Sie einen Namenskonflikt erhalten, da dies Sie nicht davor schützen kann, die Klasse B zweimal zu definieren, einmal die ursprüngliche und einmal die verspottete Version.

32
Konrad Kleine

Wenn Sie sich sicher sind, dass Sie diesen Code niemals in einem Compiler verwenden werden, der ihn nicht unterstützt (Windows/VS, GCC und Clang sind Beispiele für Compiler, die ihn do unterstützen), können Sie dies Verwenden Sie #pragma auf jeden Fall einmal ohne Bedenken.

Sie können auch einfach beides verwenden (siehe Beispiel unten), um die Portabilität und Kompiliergeschwindigkeit auf kompatiblen Systemen zu erhöhen

#pragma once
#ifndef _HEADER_H_
#define _HEADER_H_

...

#endif
22
Donnie DeBoer

Nach einer ausführlichen Diskussion über den vermeintlichen Performance-Kompromiss zwischen #pragma once Und #ifndef Wachen gegen das Argument der Richtigkeit oder nicht (ich habe mich für #pragma once Ausgesprochen) Zu diesem Zweck habe ich mich vor relativ kurzer Zeit entschlossen, die Theorie zu testen, dass #pragma once schneller ist, da der Compiler nicht versuchen muss, eine bereits enthaltene Datei erneut #include zu erstellen.

Für den Test habe ich automatisch 500 Header-Dateien mit komplexen Abhängigkeiten generiert und eine .c - Datei erstellt, die alle #include - Dateien enthält. Ich habe den Test auf drei Arten durchgeführt, einmal mit nur #ifndef, Einmal mit nur #pragma once Und einmal mit beiden. Ich habe den Test auf einem ziemlich modernen System durchgeführt (einem MacBook Pro von 2014, auf dem OSX mit XCodes Clang-Paket und der internen SSD ausgeführt wird).

Zunächst der Testcode:

#include <stdio.h>

//#define IFNDEF_GUARD
//#define PRAGMA_ONCE

int main(void)
{
    int i, j;
    FILE* fp;

    for (i = 0; i < 500; i++) {
        char fname[100];

        snprintf(fname, 100, "include%d.h", i);
        fp = fopen(fname, "w");

#ifdef IFNDEF_GUARD
        fprintf(fp, "#ifndef _INCLUDE%d_H\n#define _INCLUDE%d_H\n", i, i);
#endif
#ifdef PRAGMA_ONCE
        fprintf(fp, "#pragma once\n");
#endif


        for (j = 0; j < i; j++) {
            fprintf(fp, "#include \"include%d.h\"\n", j);
        }

        fprintf(fp, "int foo%d(void) { return %d; }\n", i, i);

#ifdef IFNDEF_GUARD
        fprintf(fp, "#endif\n");
#endif

        fclose(fp);
    }

    fp = fopen("main.c", "w");
    for (int i = 0; i < 100; i++) {
        fprintf(fp, "#include \"include%d.h\"\n", i);
    }
    fprintf(fp, "int main(void){int n;");
    for (int i = 0; i < 100; i++) {
        fprintf(fp, "n += foo%d();\n", i);
    }
    fprintf(fp, "return n;}");
    fclose(fp);
    return 0;
}

Und jetzt meine verschiedenen Testläufe:

folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.164s
user    0m0.105s
sys 0m0.041s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.140s
user    0m0.097s
sys 0m0.018s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.193s
user    0m0.143s
sys 0m0.024s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.153s
user    0m0.101s
sys 0m0.031s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.170s
user    0m0.109s
sys 0m0.033s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.155s
user    0m0.105s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ gcc pragma.c -DPRAGMA_ONCE -DIFNDEF_GUARD
folio[~/Desktop/pragma] fluffy$ ./a.out 
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.153s
user    0m0.101s
sys 0m0.027s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.181s
user    0m0.133s
sys 0m0.020s
folio[~/Desktop/pragma] fluffy$ time gcc -E main.c  > /dev/null

real    0m0.167s
user    0m0.119s
sys 0m0.021s
folio[~/Desktop/pragma] fluffy$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/include/c++/4.2.1
Apple LLVM version 8.1.0 (clang-802.0.42)
Target: x86_64-Apple-darwin17.0.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Wie Sie sehen können, waren die Versionen mit #pragma once Tatsächlich etwas schneller zu verarbeiten als die mit #ifndef - nur eine, aber Der Unterschied war vernachlässigbar und würde durch die Zeit, die das Erstellen und Verknüpfen des Codes tatsächlich in Anspruch nehmen würde, weit überschattet. Wenn die Codebasis groß genug ist, kann dies tatsächlich zu einem Zeitunterschied von einigen Sekunden führen, aber zwischen modernen Compilern, die in der Lage sind, die #ifndef - Schutzfunktionen zu optimieren, und der Tatsache, dass Betriebssysteme über gute Festplatten-Caches verfügen, und den zunehmenden Geschwindigkeiten In Bezug auf die Speichertechnologie scheint das Leistungsargument, zumindest auf einem typischen heutigen Entwicklersystem, umstritten zu sein. Ältere und exotischere Build-Umgebungen (z. B. auf einer Netzwerkfreigabe gehostete Header, Erstellen von Bändern usw.) können die Gleichung etwas ändern. Unter diesen Umständen erscheint es jedoch sinnvoller, zunächst eine weniger fragile Build-Umgebung zu erstellen.

Tatsache ist, dass #ifndef Mit Standardverhalten standardisiert ist, während #pragma once Dies nicht ist, und #ifndef Auch seltsame Fälle von Dateisystem- und Suchpfadecken behandelt, während #pragma once kann durch bestimmte Dinge sehr verwirrt werden, was zu falschem Verhalten führt, auf das der Programmierer keinen Einfluss hat. Das Hauptproblem bei #ifndef Ist, dass Programmierer schlechte Namen für ihre Wachen auswählen (bei Namenskollisionen usw.), und selbst dann ist es für den Benutzer einer API durchaus möglich, diese schlechten Namen mit #undef Zu überschreiben. - vielleicht keine perfekte Lösung, aber es ist möglich , während #pragma once keinen Rückgriff hat, wenn der Compiler fälschlicherweise ein #include.

Also, obwohl #pragma once Nachweislich (etwas) schneller ist, stimme ich nicht zu, dass dies an und für sich ein Grund dafür ist Verwenden Sie es über #ifndef Wachen.

[~ # ~] edit [~ # ~] : Dank des Feedbacks von @LightnessRacesInOrbit habe ich die Anzahl der Header-Dateien erhöht und den Test auf geändert Führen Sie nur den Präprozessor-Schritt aus, um die Zeit zu sparen, die beim Kompilieren und Verknüpfen aufgewendet wurde (was zuvor trivial und jetzt nicht mehr vorhanden war). Wie erwartet ist das Differential ungefähr gleich.

19
fluffy

Ich kümmere mich im Allgemeinen nicht um #pragma once, da mein Code manchmal mit etwas anderem als MSVC oder GCC kompiliert werden muss (Compiler für eingebettete Systeme haben nicht immer das # Pragma).

Also muss ich sowieso #include guards benutzen. Ich könnte auch #pragma once wie einige Antworten vermuten lassen, aber es scheint nicht viel Grund zu geben und es wird oft unnötige Warnungen bei den Compilern auslösen, die dies nicht unterstützen.

Ich bin nicht sicher, welche Zeitersparnis das Pragma bringen könnte. Ich habe gehört, dass Compiler im Allgemeinen bereits erkennen, wenn ein Header nur Kommentare außerhalb der Guard-Makros enthält, und die #pragma once Äquivalent in diesem Fall (dh, die Datei wird nie wieder verarbeitet). Aber ich bin nicht sicher, ob es wahr ist oder nur ein Fall von Compilern könnte diese Optimierung durchführen.

In beiden Fällen ist es für mich einfacher, #include Guards zu verwenden, die überall funktionieren und sich nicht weiter darum kümmern.

15
Michael Burr

Es gibt eine verwandte Frage auf die ich antwortete :

#pragma once hat einen Nachteil (abgesehen davon, dass es sich nicht um Standarddateien handelt). Wenn Sie dieselbe Datei an verschiedenen Speicherorten haben (wir haben dies, weil unser Build-System Dateien kopiert), wird der Compiler davon ausgehen, dass dies unterschiedliche Dateien sind.

Ich füge die Antwort auch hier hinzu, falls jemand über diese Frage stolpert und nicht über die andere.

10
Motti

Ich denke, das erste, was Sie tun sollten, ist zu überprüfen, ob dies wirklich einen Unterschied macht, dh. Sie sollten zuerst die Leistung testen. Eine der Suchanfragen in Google ergab this .

Auf der Ergebnisseite sind die Spalten für mich ein wenig veraltet, aber es ist klar, dass zumindest bis VC6 Microsoft die von den anderen Tools verwendeten Include Guard-Optimierungen nicht implementiert hat. Wenn der Include-Guard intern war, dauerte es 50-mal länger als bei einem externen Include-Guard (externe Include-Guards sind mindestens so gut wie #pragma). Aber lassen Sie uns die möglichen Auswirkungen davon betrachten:

Gemäß den dargestellten Tabellen beträgt die Zeit zum Öffnen und Überprüfen des Includes das 50-fache der Zeit eines # Pragma-Äquivalents. Die tatsächliche Zeit dafür wurde jedoch bereits 1999 mit 1 Mikrosekunde pro Datei gemessen!

Wie viele doppelte Überschriften hat eine einzelne TU? Dies hängt von Ihrem Stil ab, aber wenn wir sagen, dass eine durchschnittliche TU 100 Duplikate hat, dann im Jahr 1999 Wir zahlen möglicherweise 100 Mikrosekunden pro TE. Mit Festplattenverbesserungen ist dies wahrscheinlich inzwischen erheblich niedriger, aber selbst dann, wenn vorkompilierte Header und korrekte Abhängigkeiten vorhanden sind, ist die Nachverfolgung der kumulierten Gesamtkosten für ein Projekt mit ziemlicher Sicherheit ein unbedeutender Teil Ihrer Erstellungszeit .

Nun, auf der anderen Seite, so unwahrscheinlich es auch sein mag: Wenn Sie jemals zu einem Compiler wechseln, der #pragma once Nicht unterstützt, sollten Sie überlegen, wie lange es dauern wird, Ihre gesamte Quellbasis zu aktualisieren, um Include-Guards zu haben eher als #pragma?

Es gibt keinen Grund, warum Microsoft eine Include-Guard-Optimierung nicht auf die gleiche Weise implementieren konnte wie GCC und jeder andere Compiler (kann tatsächlich jemand bestätigen, ob die neueren Versionen dies implementieren?). IMHO, #pragma once Schränkt Ihre Auswahl an alternativen Compilern kaum ein.

9
Richard Corden

#pragma once ermöglicht es dem Compiler, die Datei vollständig zu überspringen, wenn sie erneut auftritt - anstatt die Datei zu analysieren, bis die # include-Guards erreicht sind.

Daher ist die Semantik etwas anders, aber sie ist identisch, wenn sie so verwendet wird, wie sie verwendet werden soll.

Beides zu kombinieren ist wahrscheinlich der sicherste Weg, da Sie im schlimmsten Fall (ein Compiler, der unbekannte Pragmas als tatsächliche Fehler und nicht nur Warnungen kennzeichnet) die Pragmas selbst entfernen müssten.

Wenn Sie Ihre Plattformen auf "Mainstream-Compiler auf dem Desktop" beschränken, können Sie die # include-Guards sicher weglassen, aber auch das ist mir unangenehm.

OT: Wenn Sie weitere Tipps/Erfahrungen zur Beschleunigung von Builds haben, wäre ich neugierig.

4
peterchen

Für diejenigen, die #pragma einmal verwenden möchten und gleichzeitig Wachen verwenden möchten: Wenn Sie MSVC nicht verwenden, werden Sie von #pragma einmal nicht viel Optimierung erhalten.

Und Sie sollten "#pragma once" nicht in eine Kopfzeile einfügen, die mehrere Male enthalten sein soll, wobei jede Einbeziehung möglicherweise einen anderen Effekt hat.

Hier ist eine ausführliche Diskussion mit Beispielen zu #pragma once usage.

1
Deqing

Auf Erklärung von Konrad Kleine oben.

Eine kurze Zusammenfassung:

  • wenn wir # pragma once verwenden, liegt es in der Verantwortung des Compilers, die Einfügung nicht mehr als einmal zuzulassen. Das heißt, nachdem Sie das Code-Snippet in der Datei erwähnt haben, liegt es nicht mehr in Ihrer Verantwortung.

Der Compiler sucht nun nach diesem Code-Snippet am Anfang der Datei und überspringt dessen Einbeziehung (falls bereits einmal enthalten). Dies wird definitiv die Kompilierungszeit verkürzen (im Durchschnitt und in riesigen Systemen). Im Falle von Mocks/Testumgebungen wird die Implementierung der Testfälle jedoch aufgrund von zirkulären Abhängigkeiten usw. schwierig.

  • Wenn wir nun #ifndef XYZ_H Für die Header verwenden, liegt es mehr in der Verantwortung der Entwickler, die Abhängigkeit von Headern aufrechtzuerhalten. Das heißt, wenn aufgrund einer neuen Header-Datei die Möglichkeit einer zirkulären Abhängigkeit besteht, markiert der Compiler beim Kompilieren nur einige "undefined .." - Fehlermeldungen, und es ist Aufgabe des Benutzers, die logische Verbindung/den logischen Ablauf von zu überprüfen die Entitäten und korrigieren die unsachgemäßen Einschlüsse.

Dies wird auf jeden Fall die Kompilierungszeit verlängern (da dies korrigiert und erneut ausgeführt werden muss). Außerdem, da es auf der Basis des Einbindens der Datei funktioniert, basierend auf dem definierten "XYZ_H" -Zustand, und sich immer noch beschwert, wenn es nicht in der Lage ist, alle Definitionen abzurufen.

Um solche Situationen zu vermeiden, sollten wir daher as verwenden.

#pragma once
#ifndef XYZ_H
#define XYZ_H
...
#endif

die Kombination von beiden.

1
parasrish