443 Stimmen

Ist #pragma einmal ein sicherer Include-Schutz?

Ich habe gelesen, dass es eine Compiler-Optimierung gibt, wenn man #pragma once was zu einer schnelleren Kompilierung führen kann. Ich weiß, dass dies nicht dem Standard entspricht und daher ein Problem mit der plattformübergreifenden Kompatibilität darstellen könnte.

Ist dies etwas, das von den meisten modernen Compilern auf Nicht-Windows-Plattformen (gcc) unterstützt wird?

Ich möchte Probleme bei der Kompilierung von Plattformen vermeiden, aber auch die zusätzliche Arbeit von Fallback-Guards vermeiden:

#pragma once
#ifndef HEADER_H
#define HEADER_H

...

#endif // HEADER_H

Sollte ich mir Sorgen machen? Sollte ich weitere geistige Energie darauf verwenden?

12voto

Edwin Jarvis Punkte 5650

Ich benutze es und bin zufrieden damit, da ich viel weniger tippen muss, um eine neue Überschrift zu erstellen. Es hat bei mir auf drei Plattformen gut funktioniert: Windows, Mac und Linux.

Ich habe keine Informationen über die Leistung, aber ich glaube, dass der Unterschied zwischen #pragma und dem Include Guard nichts im Vergleich zur Langsamkeit des Parsens der C++-Grammatik sein wird. Das ist das eigentliche Problem. Versuchen Sie, die gleiche Anzahl von Dateien und Zeilen mit einem C#-Compiler zu kompilieren, um den Unterschied zu sehen.

Letztendlich spielt es keine Rolle, ob Sie den guard oder das pragma verwenden.

11voto

Jonathan Leffler Punkte 694013

Mit ' #pragma once ' hat möglicherweise keine Wirkung (es wird nicht überall unterstützt - obwohl es zunehmend unterstützt wird), so dass Sie ohnehin den Code für die bedingte Kompilierung verwenden müssen. #pragma once '? Der Compiler optimiert es wahrscheinlich sowieso. Es hängt jedoch von Ihren Zielplattformen ab. Wenn alle Ihre Ziele unterstützen, dann gehen Sie vor und verwenden Sie es - aber es sollte eine bewusste Entscheidung sein, weil die Hölle losbrechen wird, wenn Sie nur das Pragma verwenden und dann auf einen Compiler portieren, der es nicht unterstützt.

7voto

Klaim Punkte 63705

Der Leistungsvorteil besteht darin, dass die Datei nicht erneut geöffnet werden muss, nachdem die #pragma-Datei gelesen wurde. Bei Guards muss der Compiler die Datei öffnen (was sehr zeitaufwändig sein kann), um die Information zu erhalten, dass der Inhalt nicht erneut aufgenommen werden soll.

Das ist nur Theorie, denn einige Compiler öffnen automatisch keine Dateien, die keinen Lesecode enthalten, für jede Kompiliereinheit.

Wie auch immer, es ist nicht der Fall für alle Compiler, so dass idealerweise #pragma einmal für plattformübergreifende Code vermieden werden müssen hat es nicht Standard überhaupt / haben keine standardisierte Definition und Wirkung. Doch praktisch ist es wirklich besser als Wachen.

Letztendlich ist die einen besseren Vorschlag können Sie nicht bekommen Um sicher zu sein, dass Sie die beste Geschwindigkeit von Ihrem Compiler erhalten, ohne das Verhalten jedes Compilers in diesem Fall überprüfen zu müssen, sollten Sie sowohl pragma once als auch guards verwenden.

#ifndef NR_TEST_H
#define NR_TEST_H
#pragma once

#include "Thing.h"

namespace MyApp
{
 // ...
}

#endif

Auf diese Weise erhalten Sie das Beste von beidem (plattformübergreifend und schnelle Kompilierung).

Da die Eingabe länger dauert, verwende ich persönlich ein Tool, das mir hilft, all das auf sehr einfache Art und Weise zu erstellen (Visual Assist X).

6voto

Omer Punkte 59

Nicht immer.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 enthält ein schönes Beispiel für zwei Dateien, die beide einbezogen werden sollten, aber aufgrund identischer Zeitstempel und Inhalte (nicht identischer Dateinamen) fälschlicherweise für identisch gehalten werden.

4voto

PRouleau Punkte 138

Ich verwende #ifndef/#define include-Guards mit Symbolen, die eine UUID wie diese:

#ifndef ARRAY__H_81945CB3_AEBB_471F_AC97_AB6C8B220314
#define ARRAY__H_81945CB3_AEBB_471F_AC97_AB6C8B220314 /* include guard */

#endif

Ich habe immer Editoren verwendet, die die UUIDs automatisch generieren konnten. Dies verhindert Namenskonflikte mit Dateien mit demselben Basisnamen aus anderen Bibliotheken und erkennt, wenn dieselbe Datei an mehreren Stellen im Dateisystem gespeichert ist.

Der Nachteil ist die Vergrößerung der Tabelle, da die Symbole viel größer sind, aber ich habe noch keine Probleme damit gesehen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X