2010-11-04 33 views
7

So che in genere si inizializza una variabile membro statica all'interno di un file cpp. Ma la mia domanda è: perché lo ha?Perché si _have_ per inizializzare una variabile membro statica C++?

Ecco un esempio:

#include <vector> 

using namespace std; 

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

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

Questo dà un errore di compilazione: undefined reference to 'A::x'

Tuttavia, questo:

#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(); 
} 

compila e funziona bene.

Posso capire se stavo inizializzando il vettore usando qualcosa di diverso dal costruttore predefinito, ma non lo sono. Voglio solo un vettore di dimensione 0 creato. Sicuramente, tutti i membri statici dovranno allocare memoria sull'inizializzazione del programma, quindi perché il compilatore non usa semplicemente il costruttore predefinito?

risposta

14

Questo è non sull'inizializzazione, è circa definizione. O più precisamente: si tratta di sapere quale unità di compilazione (cpp) terrà l'oggetto (che devono essere univocamente definito da qualche parte)

Quindi, ciò che è necessario è semplicemente quello di mettere la definizione da qualche parte, in un posto unico, cioè un cpp, per far sapere al compilatore che quando viene chiamato l'oggetto statico della classe, viene definito lì e da nessun'altra parte. (se provi a definire la tua statica in un'intestazione, ogni cpp che include questa intestazione avrà una definizione, rendendo impossibile sapere dove dovrebbe essere definito e inizializzato manualmente se è necessario per l'uso) .

+2

+1 ma è necessario eliminare uno dei duplicati. Per gli oggetti, RAII rende l'inizializzazione (anche se solo per costruttore predefinito) una conseguenza della definizione. Funziona per i puntatori grezzi, i tipi builtin come 'int'? –

+0

Intendevo dire che è possibile aggiungere l'inizializzazione lì, se lo si desidera. Aggiungerò la precisione – Klaim

+0

@Steve I costruttori di tipo POD sono solo sintattici, quindi sì funziona, ma in realtà non fa nulla (o per essere ancora più preciso, non può fare nulla - dallo standard C++). –

2

Ciò che si chiama inizializzazione è definizione. È necessario definire il membro statico da qualche parte. La parte all'interno della classe è solo una dichiarazione.

Ciò è dovuto principalmente al fatto che avere una definizione all'interno dell'intestazione causerebbe enormi problemi (poiché non si poteva includere quell'intestazione in più di una unità di traduzione senza causare più definizioni).

8

Si sta osservando dal punto di una singola unità di compilazione.

Ma il linguaggio deve presupporre che ci può potenzialmente da più unità di compilazione. Quindi ora in quale unità di compilazione viene creato l'oggetto statico? Fondamentalmente il compilatore non è autorizzato a prendere questa decisione e l'ingegnere deve prendere la decisione.

3

undefined reference to 'A::x' non è un errore del compilatore; è un errore del linker. Significa che non è possibile trovare una definizione di A::x in nessuna delle unità di traduzione collegate per formare il programma. Le variabili membro statiche hanno un collegamento esterno e devono essere definite esattamente in una unità di traduzione. Qualsiasi cosa con collegamento esterno non avrà una definizione generata dal compilatore a meno che non ne scriva uno.

Problemi correlati