1. 程式人生 > >C++類的靜態成員變數一定要初始化(分配記憶體)

C++類的靜態成員變數一定要初始化(分配記憶體)

文章轉載自https://my.oschina.net/u/1537391/blog/219432
我們知道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一個類物件不僅會分配記憶體,同時會呼叫建構函式進行初始化,所以類物件的定義和初始化總是關聯在一起。