文章轉載自https://my.oschina.net/u/1537391/blog/219432
https://blog.csdn.net/vict_wang/article/details/80994894
我們知道C++類的靜態成員變量是需要初始化的,但為什么要初始化呢。其實這句話“靜態成員變量是需要初始化的”是有一定問題的,應該說“靜態成員變量需要定義”才是准確的,而不是初始化。兩者的區別在於:初始化是賦一個初始值,而定義是分配內存。靜態成員變量在類中僅僅是聲明,沒有定義,所以要在類的外面定義,實際上是給靜態成員變量分配內存。可以通過以下幾個例子更形象的說明這個問題:
//test.cpp #include <stdio.h> class A { public: static int a; //聲明但未定義,還未分配內存 }; int main() { printf("%d", A::a); return 0; }
編譯以上代碼會出現“對‘A::a’未定義的引用”錯誤。這是因為靜態成員變量a未定義,也就是還沒有分配內存,顯然是不可以訪問的。再看如下例子:
//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了。因為類中的靜態成員變量僅僅是聲明,暫時不需分配內存,所以我們甚至可以這樣寫代碼:
//a.cpp class B; //這里我們使用前置聲明,完全不知道B是什么樣子 class A { public: static B bb;//聲明了一個類型為B的靜態成員,在這里編譯器並未給bb分配內存。 //因為僅僅是聲明bb,所以編譯器並不需要知道B是什么樣子以及要給其對應的對象分配多大的空間。 //所以使用前置聲明"class B"就可以保證編譯通過。 };
使用命令"g++ -c -o a.o a.cpp"通過編譯。對於類來說,new一個類對象不僅會分配內存,同時會調用構造函數進行初始化,所以類對象的定義和初始化總是關聯在一起。
