static關鍵字總結
static,即靜態聲明。它在 範圍、儲存方式、生命週期 等各方面影響一個變數或函數。文章將從 局部變數、全域變數、普通函數、類的static成員(包括資料成員與成員函數)來總結static。
所有的全域變數,無論是否是static的,都是儲存於靜態儲存區的。全域變數本身就是靜態儲存方式,將全域變數聲明為static是為了將變數的範圍限制在本翻譯單元中(本源檔案中),使該全域變數不能被來源程式的其他翻譯單元所引用。普通全域變數使用extren聲明可以拓展其範圍至其他翻譯單元中。
可以總結為:static改變了全域變數的範圍,而不改變變數的儲存位置與生命週期。
局部變數即在函數內定義的或在塊中定義的變數。static對局部變數的作用不同於全域變數。普通局部變數在離開其範圍(如離開定義它的函數或塊的花括弧)時即消失,而static變數卻存在於程式啟動並執行整個過程,也即是說,static聲明改變了局部變數的生命週期。普通局部變數是儲存在動態儲存裝置區的(堆),而static局部變數是儲存在靜態儲存區,因而普通局部變數在函數每次被調用時都被重新分配記憶體位址,而靜態局部變數則在程式運行過程中佔據固定的記憶體。
可以總結為:static改變了局部變數的儲存方式與生命週期,而不改變變數的範圍。
這裡的普通函數是為了與類的成員函數區別開來。函數在定義時預設是外部的,通過extren聲明即可被其他源檔案引用,static聲明將函數的範圍限制在本翻譯單元中,成為內建函式。static函數在記憶體中只有一份,普通函數在每個調用中維持一份拷貝。
可以總結為:static使得函數在記憶體中只有一份,並將函數範圍限制在當前源檔案。
另外,static有幾個優點總被提起:
1. 避免了連結時與其他源檔案中的變數命名引起衝突。
2.對於c函數而言,static對函數進行了資訊屏蔽,只給當前檔案中其他函數使用。
static聲明對類成員的作用可以這樣概括:static使得成員從“屬於類對象”變成了“屬於類,而不屬於類對象”。
對於資料成員:
1.static資料成員必須在類定義體的外部進行定義。
class BOOK{ private: //折扣 static float discount;};//在類定義體外部定義並初始化float BOOK::discount = 0.95f;
2.不像普通資料成員,static資料成員不能在建構函式中進行初始化。正如上面所說,它只能在類外部定義並初始化。然而有一個例外,整型的const static 資料成員可以在類的定義體中進行初始化。但需注意的是,const static資料成員在類的定義體中初始化時,該資料成員仍必須在類的定義體之外進行定義(不必再指定初始值了)。
class BOOK{ private: //折扣 const static int discount=1;};const int BOOK::discount;
在類內部聲明的static成員函數,在類定義體外部進行定義時無須重複指定static關鍵字。
對於static成員函數,它同樣是不屬於類對象的,因而它沒有this指標。它可以直接存取類的static資料成員,不能直接使用非static成員,原因是非static資料成員屬於類對象,使用非static資料成員時必須通過this指標來確定是這些成員屬於哪個類對象,然而上面說了,static成員函數沒有this指標。
static成員函數不能被聲明為const。實際上,成員函數被聲明為const的本質是它向編譯器保證不會通過這個函數來修改類對象在記憶體中的每一個bit的內容(可以看《effective C++》 條款03 “儘可能使用const” ),然而我們知道,static成員函數並不屬於類對象,更談不上要保證不修改某一對象的記憶體了。
另外,虛函數不能為聲明為static,為什麼呢?原因還是static成員函數沒有this指標。virtual funtion運行時綁定是多態的基礎,沒有this指標多態的概念無法踐行。】