Include Guard für jedes gesamte hpp?
-
Hallo zusammen,
ich recherchiere öfters, wie ich besser programmieren kann. Dann ist mir ein Artikel aufgefallen, der aussagt, dass man das komplette hpp in einen include guard setzen sollte.
datum.hpp
#ifndef DATUM_HPP #define DATUM_HPP ... ... ... Ende der Datei #endif
Es soll die Kompilierungszeit beschleunigen und auch andere Probleme lösen, wie zyklische Abhängigen zwischen Header Dateien. Ist das ein guter Tipp?
Ich verwende in header Dateien immer #pragma once. Aber include guards eigentlich so gut wie nie.
-
Ja, das ist nicht nur ein guter Tipp, das ist quasi ein MUSS. Denn ein mehrfacher oder zyklischer Import wäre ja schlich falsch.
#pragma once
macht das gleiche wie der Includeguard, aber mit weniger Schreibarbeit. Der wesentliche Unterschied ist, dass das streng genommen eine nicht-standardmäßige Compilererweiterung ist, wohingehen ein klassischer Includeguard garantiert immer, überall funktioniert. Du wirst aber lange suchen müssen, bis du einen Compiler findest, der das nicht unterstützt. Es gibt theoretisch noch ein paar kleine, feine Unterschiede, die aber schon eher auf der theoretischen Seite sind, als dass sie unbeabsichtigt ein Problem werden könnten.
-
@SeppJ sagte in Include Guard für jedes gesamte hpp?:
#pragma once macht das gleiche wie der Includeguard, aber mit weniger Schreibarbeit.
Das bedeutet, wenn ich #pragma once verwende, kann ich mir das sparen oder soll ich zur Sicherheit doch lieber den Includeguard trotzdem machen?
Das wir den Compiler wechseln ist extrem unwahrscheinlich und würde viel größere Probleme bringen.
-
Doppelt bringt doch nichts, wenn der Vorteil doch geringere Schreibarbeit ist. Wenn du auf 100% sicher gehen willst, dass das auch auf einem C64 compiliert, dann nimm Includeguards. Wenn du 99% sicher sein willst, und ein paar Zeichen weniger schreiben möchtest (und Szenarien verhindern möchtest, wo du dich vertippst, oder jemand anderes den gleichen Identifier benutzt hat), nimm pragma once.
-
ChatGPT 3.5 (13.05.2024):
Beide Methoden, #pragma once und Include Guards, dienen dazu, sicherzustellen, dass Header-Dateien nur einmal in einem Übersetzungsunit eingefügt werden. Es gibt jedoch einige Unterschiede zwischen den beiden Ansätzen:
#pragma once:
Es ist ein Compiler-spezifisches Feature und möglicherweise nicht portabel über verschiedene Compiler hinweg.
Es ist einfacher zu verwenden, da Sie keine speziellen Makros definieren müssen.
Es kann zu schnelleren Kompilierzeiten führen, da der Compiler feststellen kann, ob die Datei bereits eingeschlossen wurde, ohne nach vorherigen Einbeziehungen zu suchen.Include Guards:
Sie sind portabler, da sie von allen C++-Compilern unterstützt werden.
Sie erfordern das Definieren spezieller Makros, was etwas mehr Schreibarbeit bedeutet.
Sie können dazu beitragen, Konflikte zu vermeiden, wenn mehrere Header-Dateien in einem Projekt den gleichen Dateinamen haben.
Insgesamt ist die Wahl zwischen #pragma once und Include Guards oft eine Frage der persönlichen Präferenz und der spezifischen Anforderungen des Projekts. Einige Entwickler bevorzugen #pragma once wegen seiner Einfachheit, während andere sich für Include Guards entscheiden, weil sie portabler sind. In vielen modernen C++-Projekten wird #pragma once aufgrund seiner Einfachheit und Effizienz jedoch häufig verwendet.
-
#pragma once
löst auch noch das Problem doppelter Include-Guard-Namen. Wenn man viele 3rd Party Bibliotheken einsetzt kann es vorkommen, dass in verschiedenen .h Dateien der gleiche Include-Guard-Name benutzt wird, was zu üblen Fehlern führen kann. Das Problem hat man mit#pragma once
nicht mehr.
-
@DocShoe sagte in Include Guard für jedes gesamte hpp?:
#pragma once
löst auch noch das Problem doppelter Include-Guard-Namen. Wenn man viele 3rd Party Bibliotheken einsetzt kann es vorkommen, dass in verschiedenen .h Dateien der gleiche Include-Guard-Name benutzt wird, was zu üblen Fehlern führen kann. Das Problem hat man mit#pragma once
nicht mehr.Aber das umgekehrte Problem, dass manche Leute die schlechte Angewohnheit haben, abhängige Header zu kopieren oder zu linken, anstatt sich um korrekte Installation und Includeverzeichnisse zu kümmern. Dann würde der Includeguard greifen, aber nicht das Pragma. Wenn man nur lange genug sucht, findet man immer ein Argument für oder gegen jede der Seiten. In jedem normalen Projekt mit normalen Best Practices wird aber keiner dieser Unterschiede eine Rolle spielen.
-
Die Diskussion ist hoffentlich bald akademisch, wenn Module korrekt von den Compilern unterstützt werden.
-
MMn. kann man problem- und gefahrlos
#pragma once
verwenden.Im schlimmsten Fall muss man sich beim Compilerwechsel ein kleines Tool schreiben, das die
#pragma once
in normale Include-Guards umwandelt. Sollte keine Hexerei sein. Die Guard-Namen kann man dabei z.B. leicht aus GUIDs generieren. Bzw. es ist leicht möglich dass es schon fertige Tools gibt die das können - vielleicht kann es sogar Clang-Tidy. Damit kann man dann hunderte oder tausende Sourcefiles ohne grossen Aufwand umstellen wenn nötig.
-
@john-0 sagte in Include Guard für jedes gesamte hpp?:
Die Diskussion ist hoffentlich bald akademisch, wenn Module korrekt von den Compilern unterstützt werden.
Ja, kommt sicher bald
-
Wir benutzen das Embarcadero RAD Studio (ganz früher Borland), bei dem Include-Guards eine weitere Funktion erfüllen:
Die Guards müssen einem Namensschema folgen, nur dann kann die IDE den Bezug der Dateien untereinander herstellen. Der Guard der Dateifoo.h
mussFooH
lauten, ansonsten findet die IDE die zugehörige .cpp (oder .dfm) Datei nicht. Somit hat man nicht immer die freie Wahl des Namens, was in diesem Fall eine ziemlich bescheuerte Idee seitens Borlands war.
-
@Tyrdal sagte in Include Guard für jedes gesamte hpp?:
@john-0 sagte in Include Guard für jedes gesamte hpp?:
Die Diskussion ist hoffentlich bald akademisch, wenn Module korrekt von den Compilern unterstützt werden.
Ja, kommt sicher bald
Ach, die jüngeren wissen gar nicht, wie gut C++ es heute hat. Alle 3 Jahre neue Features, die auch halbwegs schnell umgesetzt werden? Wohingegen mein Code von 2010 wahrscheinlich auf einem Compiler aus den 1990ern compiliert hätte - und das lag nicht an mir.
-
@SeppJ sagte in Include Guard für jedes gesamte hpp?:
Ach, die jüngeren wissen gar nicht, wie gut C++ es heute hat. Alle 3 Jahre neue Features, die auch halbwegs schnell umgesetzt werden? Wohingegen mein Code von 2010 wahrscheinlich auf einem Compiler aus den 1990ern compiliert hätte - und das lag nicht an mir.
Die Prä-ISO-Norm Standard Library funktioniert zum Teil deutlich anders als die ISO-Norm Standard Library, weshalb auch die Header mit .h rausgeworfen wurden, und die ohne Dateiendung kamen. Dann gab es eine starke Änderung bei den String Streams, weshalb die aktuellen Header stringstreams und die alten strstreams existieren, und dann gab es noch eine Variante mit .h am Ende.