putting-Funktion Definitionen in header-Dateien
Wenn Sie wollen, um die Funktion von Definitionen in header-Dateien, es scheint, gibt es drei verschiedene Lösungen:
- markieren Sie die Funktion als
inline
- markieren Sie die Funktion als
static
- setzen Sie die Funktion in einem anonymen namespace
(Bis vor kurzem war ich nicht einmal bewusst von #1.) Also, was sind die Unterschiede zu diesen Lösungen, und wenn ich, sollte ich lieber die? Ich bin in der header-only-Welt, so dass ich wirklich brauchen, die Definitionen in den header-Dateien.
- Du hast vergessen: Schalten Sie in die Funktion Vorlagen. Das ist, was ich normalerweise bevorzuge.
- nicht static zu verwenden, das führt zu vielen unterschiedlichen Kopien und Wahnsinn.
- Der "eine Kopie in jedem anonymen namespace" - Lösung führt zu den gleichen Wahnsinn.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
static
und Unbenannte namespace-Versionen am Ende das gleiche: jede übersetzungseinheit enthält eine eigene version der Funktion, und das bedeutet, dass bei einer statischen Funktionf
, die Zeiger&f
wird anders sein in jeder übersetzungseinheit, und das Programm enthält N verschiedene Versionen vonf
(mehr code im binary).Dies ist nicht der richtige Ansatz, um eine Funktion im header, wird es N verschiedene (genau gleich) Funktionen. Wenn die Funktion enthält
static
einheimischen dann wird es N verschiedenenstatic
lokale Variablen...BEARBEITEN: Um dies deutlicher: wenn das, was Sie wollen, ist die definition einer Funktion im header, ohne die Eine Definition der Regel der richtige Ansatz ist, um die Funktion
inline
.inline
ist der richtige Ansatz? Es wäre schön, wenn Sie diese explizit.How making a function defined in header as inline,makes it bypass the ODR?
ich dachteSection $3.2/5
Adressen, aber ich war nicht sicher.Dies ist wahrscheinlich genauer, als bemühten sich in der Q aber kannst du bitte ellaborate auf dieser.inline
zu einem gratis-Funktion nicht so gut? Also, es ist nicht der richtige Ansatz, da es schwer sein wird, zu Grunde geht, wegen der unterschiedlichen Adressen, die in jeder übersetzungseinheit? Und inline ist zu bevorzugen, da es Orte die Funktion rechts unter den anderen code, so ist es kein problem mit Adressen gibt. Habe ich das richtig verstanden?inline
Fall, dass es möglicherweise mehrere Definitionen, aber es gibt eine einzelne Funktion im Programm. In der Praxis wird der linker entfernen Sie alle aber eine definition (ohne Berücksichtigung der tatsächlichen inlining, die orthogonal) und es gibt eine Garantie, dass wenn es eine out-of-line-definition es wird einzigartig sein (einzelne Adresse). Im Fall vonstatic
gibt es N Funktionen, jede mit Ihrer eigenen Adresse, jeder mit jedem eigenen Kopien von lokalen statischen Variablen, sind diejenigen, die verschiedenen - Funktionen.inline
ist orthogonal, ob der Funktionscode wird eingebettet in den call-sites oder nicht. Der Inhalt einerstatic
Funktion inlined (und Häufig auch sind, wenn Sie einfach genug, und nicht verwendet, von vielen stellen), und den Inhalt einerinline
Funktion möglicherweise nicht inlinable (zum Beispiel, wenn es verwendet recusion, dass der nicht gedreht werden kann in eine Schleife, D. H. nicht tail-Rekursion)int foo() { static int value; return ++value; }
, in einem header. Erstellen Sie mehrere übersetzungseinheiten, die die Funktion aufrufen. Im Fall voninline
jeder Anruf bekommen einen anderen Wert, der eine mehr als der Vorherige Funktion nennen, in dem Fall vonstatic
Sie alle bekommen Sie 1 als Wert.inline
ist ein Hinweis an den compiler, die letztlich bestimmen, ob inline oder nicht. Aber jetzt.. ich dachte, dass inline-Funktionen wurden einfach unter den normalen Ablauf des Codes, anstatt einencall
Unterricht, um die inline-Funktion Adresse generiert werden. Nun werden Sie sagen, "dass es möglicherweise mehrere Definitionen, aber es gibt eine einzelne Funktion im Programm.". Nicht sicher, ich verstehe das. Ja, es ist nur 1 Funktion im Binär - (1-Adresse?). Aber wie kann es eine Adresse? Da der code ist inline. Funktioniert der compiler halten eine einzige "Sicherung"...static foo()
würde tatsächlich machen dievalue
Art "nicht - statischen" für verschiedene übersetzungseinheiten. 2. Also vermute ich, dass für solche Funktionen die mit static einheimischen, Sie würde vorschlagen, dieinline
Schlüsselwort rechts?Soweit ich weiß, nur
inline
- und template-Funktionen können definiert werden in header-Dateien.static
- Funktionen sind veraltet, und die Funktionen definiert, die in einem unbenannten Namensraum (namespace) sollte stattdessen verwendet werden (siehe 7.3.1.1 p2). Wenn Sie eine Funktion definieren, die in einen unbenannten Namensraum in einer header -, dann ist jeder source-code, einschließlich header (direkt oder indirekt) eine eindeutige definition (siehe 7.3.1.1 p1). Daher sollten Funktionen nicht definiert werden in der unbenannten Namensraum in einer header-Dateien (nur in source-Dateien).Der standard verwiesen wird, die von der c++03-standard.
EDIT:
Nächste Beispiel veranschaulicht, wie Funktionen und Variablen sollten nicht definiert werden, in Unbenannte namespace in Headern :
ops.hpp enthält:
dk1.hpp enthält:
dk1.cpp enthält:
dk.cpp enthält :
Kompilieren wie diese:
und die Ausgabe :
ops die variable
a
ist für die source-Dateidk1.cpp
unddk.cpp
static
Funktionen wurden nie veraltet, nurstatic
Objekte (vor C++11).static
Funktionen (entspricht anonymous namespace) erhalten verschiedene Exemplare für jeden der TU. Wenn die Funktion re-entrant-dies ist im Grunde identisch (einige Compiler Assembler-Ebene Unterschiede) aber wenn das nicht, dann wird es andere statische Daten für die einzelnen TU. Inline-Funktionen sind gefaltet, das heißt, Sie haben nur eine Kopie der statischen Daten für jede TU.OP obviously isn't an expert
.Der OP ist einer der wenigen Experten in ALSO wer wirklich Ahnung von C++ um den Kern.Könnten Sie die Verpackung der Methoden in einer Klasse statt eines namespace. Deklarieren Sie diese Methoden als statisch und löschen Sie den Konstruktor der Klasse zu verstärken, dass dies nicht ein Objekt instanziiert werden.
Erhalten Sie das gleiche Allgemeine Verhalten, wie es die Zugehörigkeit zu einem namespace mit nur einer einzigen Implementierung.