2010-11-04 5 views
7

Ich weiß, dass Sie in der Regel eine statische Membervariable aus einer CPP-Datei initialisieren. Aber meine Frage ist: warum hast du zu?Warum _have_ Sie eine statische C++ - Membervariable initialisieren?

Hier ist ein Beispiel:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

main() { 
    int sz = A::x.size(); 
} 

Dieser einen Compiler-Fehler gibt: undefined reference to 'A::x'

Doch diese:

#include <vector> 

using namespace std; 

class A { 
    public: 
     static vector<int> x; 
}; 

// Initialize static member 
vector<int> A::x; 

main() { 
    int sz = A::x.size(); 
} 

kompiliert und läuft gut.

Ich kann verstehen, wenn ich den Vektor mit etwas anderem als dem Standardkonstruktor initialisiert habe, aber ich bin nicht. Ich möchte nur einen Vektor der Größe 0 erstellt. Sicherlich müssen alle statischen Member bei der Programminitialisierung Speicher zugewiesen werden. Warum verwendet der Compiler nicht einfach den Standardkonstruktor?

Antwort

14

Das ist nicht über die Initialisierung, es ist über Definition. Oder genauer gesagt: es geht um die Übersetzungseinheit zu wissen (CPP) hält das Objekt (die eindeutig IRGENDWO definiert werden müssen)

Also, was einfach zu gebraucht wird ist legen Sie die Definition irgendwo, in Ein eindeutiger Ort, der ein cpp ist, um dem Compiler mitzuteilen, dass das statische Objekt der Klasse dort und nirgendwo sonst definiert wird. (Wenn Sie versuchen, Ihre Static in einer Kopfzeile zu definieren, wird jede cpp, die diese Kopfzeile enthält, eine Definition haben, die es unmöglich macht zu wissen, wo sie definiert werden sollte - und manuell initialisiert, wenn sie für Sie benötigt wird) .

+2

+1 aber Sie sollten einen der Dups löschen. Bei Objekten macht RAII die Initialisierung (auch wenn nur der Standardkonstruktor) eine Konsequenz der Definition. Funktioniert das für rohe Zeiger, eingebaute Typen wie 'int'? –

+0

Ich meinte, dass Sie die Initialisierung dort hinzufügen können, wenn Sie möchten. Ich füge die Genauigkeit hinzu. – Klaim

+0

@Steve POD Typ Konstruktoren sind nur syntaktisch, also ja es funktioniert, aber es tut eigentlich nichts (oder um noch genauer zu sein, es ist nichts zu tun - nach dem C++ - Standard). –

2

Was Sie Initialisierung nennen, ist Definition. Sie müssen das statische Mitglied irgendwo definieren. Der Teil innerhalb der Klasse ist nur eine Deklaration.

Dies liegt vor allem daran, dass eine Definition innerhalb des Headers zu großen Problemen führen würde (da Sie diesen Header nicht in mehr als eine Übersetzungseinheit aufnehmen können, ohne mehrere Definitionen zu verursachen).

8

Sie betrachten es aus der Sicht einer einzigen Kompilationseinheit.

Aber die Sprache muss davon ausgehen, dass es potenziell mehrere Übersetzungseinheiten geben kann. Also, in welcher Kompilierungseinheit wird nun das statische Objekt erstellt? Grundsätzlich darf der Compiler diese Entscheidung nicht treffen und der Ingenieur muss die Entscheidung treffen.

3

undefined reference to 'A::x' ist kein Compilerfehler; Es ist ein Linkerfehler. Das bedeutet, dass eine Definition von A::x in keiner der Übersetzungseinheiten gefunden werden kann, die zu Ihrem Programm verknüpft sind. Statische Elementvariablen haben eine externe Verknüpfung und müssen in genau einer Übersetzungseinheit definiert sein. Alles mit externer Verknüpfung wird keine vom Compiler erzeugte Definition haben, es sei denn, Sie schreiben eine.

Verwandte Themen