Ich habe gelesen, dass es bei der Verwendung einige Compiler-Optimierungen gibt, #pragma once
die zu einer schnelleren Kompilierung führen können. Ich erkenne, dass dies nicht dem Standard entspricht und daher ein plattformübergreifendes Kompatibilitätsproblem darstellen kann.
Wird dies von den meisten modernen Compilern auf Nicht-Windows-Plattformen (gcc) unterstützt?
Ich möchte Probleme bei der Plattformkompilierung vermeiden, aber auch die zusätzliche Arbeit von Fallback-Wachen vermeiden:
#pragma once
#ifndef HEADER_H
#define HEADER_H
...
#endif // HEADER_H
Sollte ich besorgt sein? Sollte ich dafür weitere geistige Energie aufwenden?
c++
include-guards
Ryan Emerle
quelle
quelle
#pragma once
einige Probleme mit der Klassenansicht in VS 2008 vermieden werden. Ich bin gerade dabei, Include-Wachen loszuwerden und sie#pragma once
aus diesem Grund durch alle zu ersetzen .Antworten:
Die Verwendung
#pragma once
sollte auf jedem modernen Compiler funktionieren, aber ich sehe keinen Grund, keinen Standard-#ifndef
Include-Guard zu verwenden. Es funktioniert gut. Die einzige Einschränkung ist, dass GCC#pragma once
vor Version 3.4 nicht unterstützt hat .Ich habe auch festgestellt, dass es zumindest bei GCC den Standard-
#ifndef
Include-Guard erkennt und optimiert , sodass er nicht viel langsamer sein sollte als#pragma once
.quelle
#pragma once
ist im Allgemeinen schneller, da die Datei nicht vorverarbeitet wird.ifndef/define/endif
erfordert sowieso eine Vorverarbeitung, denn nach diesem Block kann man (theoretisch) etwas Kompilierbares haben#ifndef FOO_BAR_H
normalerweise für eine Datei wie "foo_bar.h". Wenn Sie diese Datei später umbenennen, sollten Sie die Include-Schutzvorrichtungen entsprechend anpassen, um mit dieser Konvention übereinzustimmen? Wenn Sie zwei unterschiedliche foo_bar.h an zwei verschiedenen Stellen in Ihrem Codebaum haben, müssen Sie sich jeweils zwei verschiedene Symbole vorstellen. Die kurze Antwort lautet:#pragma once
Wenn Sie wirklich in einer Umgebung kompilieren müssen, die dies nicht unterstützt, fügen Sie Include-Schutzvorrichtungen für diese Umgebung hinzu.#pragma once
hat einen Nachteil (außer nicht standardmäßig zu sein): Wenn Sie dieselbe Datei an verschiedenen Speicherorten haben (wir haben dies, weil unser Build-System Dateien kopiert), wird der Compiler denken, dass dies unterschiedliche Dateien sind.quelle
#ifdef
, kann sich auch der Makrowert unterscheiden.Ich wünschte
#pragma once
(oder so ähnlich) wäre im Standard gewesen. Include-Wachen sind keine große Sache (aber es scheint ein wenig schwierig zu sein, sie den Leuten zu erklären, die die Sprache lernen), aber es scheint ein kleiner Ärger zu sein, der hätte vermieden werden können.In der Tat, da das
#pragma once
Verhalten in 99,98% der Fälle das gewünschte Verhalten ist, wäre es schön gewesen, wenn das Verhindern der mehrfachen Einbeziehung eines Headers automatisch vom Compiler behandelt worden wäre, mit einem#pragma
oder etwas, das eine doppelte Einbeziehung ermöglicht.Aber wir haben was wir haben (außer dass Sie es vielleicht nicht haben
#pragma once
).quelle
#import
.Ich weiß nichts über Leistungsvorteile, aber es funktioniert auf jeden Fall. Ich verwende es in allen meinen C ++ - Projekten (vorausgesetzt, ich verwende den MS-Compiler). Ich finde es effektiver als zu verwenden
Es erledigt den gleichen Job und füllt den Präprozessor nicht mit zusätzlichen Makros.
GCC unterstützt
#pragma once
offiziell ab Version 3.4 .quelle
GCC unterstützt
#pragma once
seit 3.4, siehe http://en.wikipedia.org/wiki/Pragma_once für weitere Compiler-Unterstützung.Der große Vorteil, den ich bei der Verwendung
#pragma once
von Wachen sehe , besteht darin, Fehler beim Kopieren / Einfügen zu vermeiden.Seien wir ehrlich: Die meisten von uns starten kaum eine neue Header-Datei von Grund auf neu, sondern kopieren einfach eine vorhandene und passen sie an unsere Bedürfnisse an. Es ist viel einfacher, eine Arbeitsvorlage zu erstellen,
#pragma once
anstatt Schutzvorrichtungen einzuschließen. Je weniger ich die Vorlage ändern muss, desto weniger Fehler treten auf. Dasselbe Include Guard in verschiedenen Dateien zu haben, führt zu seltsamen Compilerfehlern und es dauert einige Zeit, um herauszufinden, was schief gelaufen ist.TL; DR:
#pragma once
ist einfacher zu bedienen.quelle
Ich benutze es und bin damit zufrieden, da ich viel weniger eingeben muss, um einen neuen Header zu erstellen. Es hat auf drei Plattformen gut funktioniert: Windows, Mac und Linux.
Ich habe keine Leistungsinformationen, aber ich glaube, dass der Unterschied zwischen #pragma und dem Include Guard nichts im Vergleich zu der Langsamkeit beim Parsen der C ++ - Grammatik ist. Das ist das eigentliche Problem. Versuchen Sie beispielsweise, die gleiche Anzahl von Dateien und Zeilen mit einem C # -Compiler zu kompilieren, um den Unterschied festzustellen.
Am Ende spielt es keine Rolle, die Wache oder das Pragma zu benutzen.
quelle
Die Verwendung von '
#pragma once
' hat möglicherweise keine Auswirkung (sie wird nicht überall unterstützt - obwohl sie zunehmend unterstützt wird). Sie müssen also trotzdem den bedingten Kompilierungscode verwenden. In diesem Fall sollten Sie sich mit '#pragma once
' beschäftigen. Der Compiler optimiert es wahrscheinlich trotzdem. Dies hängt jedoch von Ihren Zielplattformen ab. Wenn alle Ihre Ziele es unterstützen, verwenden Sie es - aber es sollte eine bewusste Entscheidung sein, denn die Hölle bricht los, wenn Sie nur das Pragma verwenden und dann auf einen Compiler portieren, der es nicht unterstützt.quelle
Der Leistungsvorteil besteht darin, dass die Datei nach dem Lesen des #pragma nicht erneut geöffnet werden muss. Bei Wachen muss der Compiler die Datei öffnen (was zeitaufwändig sein kann), um die Informationen zu erhalten, die den Inhalt nicht wieder enthalten sollten.
Dies ist nur deshalb theoretisch, weil einige Compiler nicht automatisch Dateien öffnen, in denen kein Lesecode für jede Kompilierungseinheit enthalten war.
Wie auch immer, es ist nicht bei allen Compilern der Fall, daher muss #pragma idealerweise einmal für plattformübergreifenden Code vermieden werden, da es überhaupt nicht Standard ist / keine standardisierte Definition und Wirkung hat. Praktisch ist es jedoch wirklich besser als Wachen.
Am Ende ist der bessere Vorschlag , um sicherzustellen, dass Ihr Compiler die beste Geschwindigkeit bietet, ohne in diesem Fall das Verhalten jedes Compilers überprüfen zu müssen, die Verwendung von Pragma einmal und Guards.
Auf diese Weise erhalten Sie das Beste aus beiden (plattformübergreifend und bei der Kompilierungsgeschwindigkeit).
Da das Tippen länger dauert, verwende ich persönlich ein Tool, um all das auf sehr schnelle Weise zu generieren (Visual Assist X).
quelle
pragma
nach demifndef
? Gibt es einen Vorteil?Nicht immer.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 enthält ein schönes Beispiel für zwei Dateien, die beide enthalten sein sollen, aber aufgrund identischer Zeitstempel und Inhalte fälschlicherweise als identisch angesehen werden (nicht identischer Dateiname). .
quelle
#pragma once
ist nicht Standard, also ist alles, was ein Compiler entscheidet, "richtig". Dann können wir natürlich darüber sprechen, was "erwartet" und was "nützlich" ist.Verwenden von gcc 3.4 und 4.1 bei sehr großen Bäumen (manchmal unter Verwendung von distcc ) habe ich noch keine Beschleunigung festgestellt, wenn #pragma einmal anstelle oder in Kombination mit Standard-Include-Wachen verwendet wird.
Ich sehe wirklich nicht ein, wie es sich lohnt, ältere Versionen von gcc oder sogar andere Compiler zu verwirren, da es keine wirklichen Einsparungen gibt. Ich habe nicht alle verschiedenen Entlinter ausprobiert, aber ich bin bereit zu wetten, dass dies viele von ihnen verwirren wird.
Ich wünschte auch, es wäre früh angenommen worden, aber ich kann das Argument "Warum brauchen wir das, wenn ifndef einwandfrei funktioniert?" Sehen. Angesichts der vielen dunklen Ecken und Komplexitäten von C sind Wachen eines der einfachsten und selbsterklärendsten Dinge. Wenn Sie nur ein kleines Wissen über die Funktionsweise des Präprozessors haben, sollten diese selbsterklärend sein.
Wenn Sie jedoch eine erhebliche Beschleunigung feststellen, aktualisieren Sie bitte Ihre Frage.
quelle
Heutzutage sind Wachen der alten Schule so schnell wie ein #Pragma. Selbst wenn der Compiler sie nicht speziell behandelt, stoppt er dennoch, wenn #ifndef WHATEVER und WHATEVER definiert sind. Das Öffnen einer Datei ist heute spottbillig. Selbst wenn es eine Verbesserung geben würde, würde dies in der Größenordnung von Millisekunden liegen.
Ich benutze #pragma einfach nicht einmal, da es keinen Nutzen hat. Um Konflikte mit anderen Include-Wachen zu vermeiden, verwende ich Folgendes: CI_APP_MODULE_FILE_H -> CI = Company Initials; APP = Anwendungsname; der Rest ist selbsterklärend.
quelle
Der Hauptunterschied besteht darin, dass der Compiler die Header-Datei öffnen musste, um den Include Guard zu lesen. Im Vergleich dazu bewirkt Pragma einmal, dass der Compiler die Datei verfolgt und keine Datei-E / A ausführt, wenn er auf ein anderes Include für dieselbe Datei stößt. Das mag vernachlässigbar klingen, kann aber leicht mit großen Projekten skaliert werden, insbesondere mit Projekten ohne guten Header, die Disziplinen enthalten.
Allerdings sind Compiler (einschließlich GCC) heutzutage klug genug, um Wachen einmal wie Pragma zu behandeln. dh sie öffnen die Datei nicht und vermeiden die Strafe für Datei-E / A.
In Compilern, die Pragma nicht unterstützen, habe ich manuelle Implementierungen gesehen, die etwas umständlich sind.
Ich persönlich mag #pragma einmal Ansatz, da es den Aufwand von Namenskollisionen und möglichen Tippfehlern vermeidet. Im Vergleich dazu ist es auch eleganter. Für tragbaren Code sollte es jedoch nicht schaden, beides zu haben, es sei denn, der Compiler beschwert sich darüber.
quelle
#pragma once
zuvor!Wenn wir msvc oder Qt (bis zu Qt 4.5) verwenden, da GCC (bis zu 3.4), msvc beide unterstützen
#pragma once
, kann ich keinen Grund sehen, nicht zu verwenden#pragma once
.Der Name der Quelldatei ist normalerweise der gleiche wie der Klassenname, und wir wissen, dass wir manchmal einen Refactor benötigen , um den Klassennamen umzubenennen. Dann mussten wir auch den Namen ändern
#include XXXX
, daher denke ich, dass die manuelle Pflege#include xxxxx
keine kluge Arbeit ist. Selbst mit der Visual Assist X-Erweiterung ist die Pflege von "xxxx" keine notwendige Arbeit.quelle
Zusätzlicher Hinweis für die Leute, die denken, dass eine automatische einmalige Einbeziehung von Header-Dateien immer erwünscht ist: Ich erstelle seit Jahrzehnten Codegeneratoren mit doppelter oder mehrfacher Einbeziehung von Header-Dateien. Insbesondere für die Generierung von Protokollbibliotheks-Stubs finde ich es sehr komfortabel, einen extrem portablen und leistungsstarken Codegenerator ohne zusätzliche Tools und Sprachen zu haben. Ich bin nicht der einzige Entwickler, der dieses Schema verwendet, wie die X-Macros in diesem Blog zeigen. Dies wäre ohne die fehlende automatische Bewachung nicht möglich.
quelle
X-Macro
Funktion sehen, aber es ist nicht die Hauptverwendung von include. Sollte es nicht umgekehrt sein wie Header unguard / # pragma multi, wenn wir bei DRY bleiben?