咱們知道C++類的靜態成員變量是須要初始化的,但爲何要初始化呢。函數
其實這句話「靜態成員變量是須要初始化的」是有必定問題的,應該說「靜態成員變量須要定義」纔是準確的,而不是初始化。spa
二者的區別在於:初始化是賦一個初始值,而定義是分配內存。code
靜態成員變量在類中僅僅是聲明,沒有定義,因此要在類的外面定義,其實是給靜態成員變量分配內存。
對象
能夠經過如下幾個例子更形象的說明這個問題:內存
//test.cpp #include <stdio.h> class A { public: static int a; //聲明但未定義 }; int main() { printf("%d", A::a); return 0; }
編譯以上代碼會出現「對‘A::a’未定義的引用」錯誤。這是由於靜態成員變量a未定義,也就是尚未分配內存,顯然是不能夠訪問的。編譯器
再看以下例子:io
//test.cpp #include <stdio.h> class A { public: static int a; //聲明但未定義 }; int A::a = 3; //定義了靜態成員變量,同時初始化。也能夠寫"int A:a;",即不給初值,一樣能夠經過編譯 int main() { printf("%d", A::a); return 0; }
這樣就對了,由於給a分配了內存,因此能夠訪問靜態成員變量a了。編譯
由於類中的靜態成員變量僅僅是聲明,暫時不需分配內存,因此咱們甚至能夠這樣寫代碼:class
//a.cpp class B; //這裏咱們使用前置聲明,徹底不知道B是什麼樣子 class A { public: static B bb;//聲明瞭一個類型爲B的靜態成員,在這裏編譯器並未給bb分配內存。 //由於僅僅是聲明bb,因此編譯器並不須要知道B是什麼樣子以及要給其對應的對象分配多大的空間。 //因此使用前置聲明"class B"就能夠保證編譯經過。 };
使用命令"g++ -c -o a.o a.cpp"經過編譯。test
對於類來講,new一個類對象不只會分配內存,同時會調用構造函數進行初始化,因此類對象的定義和初始化老是關聯在一塊兒。