it-swarm.com.de

statische vs. nicht statische Variablen im Namespace

Ich habe einen Namespace foo, der eine ganze Zahl bar enthält, die so deklariert ist ...

foo.h:

namespace foo {
    int bar;
}

Wenn ich nun foo.h nur in eine Datei einbinde, funktioniert das gut. Ein Problem entsteht jedoch, wenn ich foo.h aus zwei oder mehr Dateien einbezieht: Ich erhalte einen Linker-Fehler. Ich habe herausgefunden, dass ich, wenn ich bar als static deklariere, foo.h in mehr als einer Datei einfügen kann. Dies erscheint mir seltsam, da mir nicht bewusst war, dass man eine statische Variable innerhalb eines Namespaces deklarieren konnte. (was bedeutet das überhaupt?)

Warum funktioniert das? Und was noch wichtiger ist, warum funktioniert es nicht ohnestatic? Was bedeutet static bei Verwendung in einer namespace?

34
Michael Dorst

Es gibt mehrere Bedeutungen für static in verschiedenen Kontexten. In diesem speziellen Kontext bedeutet dies, dass die Variable eine interne Verknüpfung hat und somit jede Übersetzungseinheit, die diesen Header enthält, eine eigene Kopie der Variablen hat.

Beachten Sie, dass dies zwar den Linker-Fehler ignoriert, jedoch eine separate foo::bar-Variable für jede der generierten Objektdateien verwaltet (Änderungen werden nicht in verschiedenen Objektdateien sichtbar).

Wenn Sie eine einzelne Variable wünschen, sollten Sie diese im Header als extern deklarieren und eine einzige Definition in einer Übersetzungseinheit angeben.

Wenn Sie eine Variable als static deklarieren, bedeutet dies, dass ihr scope auf die angegebene Übersetzungseinheit beschränkt ist nur. Ohne static ist der Gültigkeitsbereich global.

Wenn Sie eine Variable als static innerhalb einer .h-Datei (innerhalb oder ohne namespace; egal) deklarieren und diese Header-Datei in verschiedene .cpp-Dateien einschließen, wird die static-Variable lokal für jede der .cpp-Dateien festgelegt.
Nun hat jede .cpp-Datei, die diesen Header enthält, eine eigene Kopie dieser Variablen.

Ohne das Schlüsselwort static generiert der Compiler nur eine Kopie dieser Variablen. Sobald Sie die Header-Datei in mehrere .cpp-Dateien einschließen, wird der Linker über mehrere Definitionen klagen.

24
iammilind

Das Problem wird durch mehrere Definitionen der Variablen verursacht. Die Definitionen in verschiedenen Übersetzungseinheiten stehen in Konflikt miteinander, so wie mehrere Nicht-Inline-Funktionsdefinitionen nicht funktionieren würden.

Wenn Sie die Variable als statisch definieren, geben Sie der Variablen die interne Verknüpfung, sodass jede Übersetzungseinheit ihre eigene unabhängige Kopie hat.

Wahrscheinlich möchten Sie eigentlich nur die Deklaration in einen Header (mit extern) und dann die Definition in eine Implementierungsdatei einfügen.

4
bames53

Beachten Sie auch, dass const int im Namespace (global) in C++ static standardmäßig implizit hinzugefügt wurde: Definiere konstante Variablen in C++ - Header

Um besser zu verstehen, was los ist, führen Sie eine readelf in den ELF-Objektdateien der Kompilierung aus, und Sie werden deutlich erkennen, ob Symbole doppelt definiert sind oder nicht. Hier ein detailliertes Beispiel: Was bedeutet "statisch" in C?