注意:
C++靜態成員變量是用static修飾的成員變量,不屬於對象的一部分,而是類一部分,因此可以在沒有實例化任何對象的時候使用靜態成員變量。但是必須初始化它。
之所以必須初始化它是因為:全局靜態變量自動初始化,但是局部變量
由於靜態變量只能被初始化一次,所以初始化成員變量不要放在如下地方:1.類的構造函數構造函數可能多次被調用);2.頭文件中頭文件可能被包含入多個地方,也可能被執行多次)。應該放在應用程序中,類以外的任何地方初始化,例如:在main中,或全局函數中,或任何函數之外:
所有的對象(不僅僅是靜態對象)初始化都只有一次
因為a初始化為1之後,一直都沒有銷毀(因為是static),所以不會再次初始化
內存分配方式有三種:
1)從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。
2)在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。
3)從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。
類的靜態成員變量和函數中的靜態變量一樣,在編譯的時候就分配內存了,直到程序退出才釋放,並不是隨著對象的刪除而釋放的:
類的靜態成員變量為什麼必須得在類外初始化?
我的理解: 由於靜態變量在編譯期間必須初始化,全局變量的靜態或者非靜態的變量都可以賦初值0。而類中的變量要用構造函數來初始化,但是在編譯期間沒有創造對象,所以就沒有運行構造方法。故在編譯期間沒有給類的靜態變量初始化。所以要在類外 main之前要給該靜態變量初始化,不管該靜態變量的作用域為private還是public,因為編譯期間private沒有影響。但是一旦進入運行時,就不可以調用類中的private變量。
調用的時候可以通過對象調用,也可以通過類直接調用
class A
{
public:
int i; //有默認值
};
class B
{
public:
static int n;
static A Aobj;
};
int B::n = 1; //靜態成員變量的初始化
A B::Aobj; //靜態成員變量的初始化(實例化)
void main()
{
B Bobj;
printf("B::n=%d Bobj.n=%d Bobj.Aobj.i=%d/n", B::n, Bobj.n, Bobj.Aobj.i);
}
私有的靜態成員變量也是放在類外初始化的.這看起來跟它的私有屬性不相符.
再做下面的測試,發現了一個有趣的現象.
class B
{
staticint i;
public:
B(){i=3;}; //把這行注釋掉,輸出變成2
int p(){return i;};
};
int B::i = 2; //把這行注釋掉,編譯報錯
void main()
{
B Bobj;
printf("private: static int B::i=%d/n", Bobj.p()); //輸出3
}
1、“這樣看來.類外的初始化那一行根本沒有起到初始化的作用.它賦的值根本沒用.(對私有靜態成員變量是這樣.公有的還是有作用的)“ 這句話是不對的!!!
因為 對於static成員變量是否是private數據並沒有影響,因為設定static成員變量初值時,不受任何存取權限的束縛,
而靜態變量賦值是在編譯階段,所以早於構造函數,當類聲明對象時 i=3覆蓋了前面的值。所以才是 3
2、當把B(){i=3;};注掉時,沒有了構造函數裡的賦值覆蓋,所以結果是2 ,親測
3、因為由於靜態變量只能被初始化一次,所以放在函數體外或全局函數中
不過要注意的是,static成員變量的類型要出現在初始化語句中,因為這是初始化操作,不是賦值操作。static成員變量是在初始化而不是在類聲明時候)才定義出來的。如果沒有初始化操作,會產生鏈接錯誤
本文出自 “燃燒技術的活力” 博客,請務必保留此出處http://boyishachang.blog.51cto.com/3485129/1285956