C++老鳥日記033 static兩種基本含義
C++老鳥日記交流群:870038457
網易雲課堂:女兒叫老白
網易雲課堂免費課程:《C++跨平臺開發中的編譯錯誤》
網易雲課堂免費課程:《C++老鳥日記》
微信公眾號: 星點課堂
新浪微博:女兒叫老白
----------------------------------------------------------------------------
引言:
----------------------------------------------------------------------------
static關鍵字用來定義變數的作用域或者生存期。一個 extern變數則是全域性可見的,而static則表明該變數僅在區域性可見。static變數僅初始化一次,那麼它在記憶體的什麼位置呢?在堆還是棧上呢?今天,我們就來討論一下static關鍵字。
正文:
----------------------------------------------------------------------------
在C/C++中,static有兩個基本含義:
第一個基本含義是指static變數定義在靜態儲存區,也就是static變數既不在堆上也不在棧上,這是編譯器專門分配的一塊特殊儲存區。
第二個基本含義指static變數是區域性可見的。它僅在定義它的編譯單元中可見。如果定義在函式體內,則僅在函式體內可見,如果定義在類內,則僅在類的內部可見,如果定義在檔案中(函式體的外部、類的外部),那麼僅在該檔案內可見。
static變數僅在函式呼叫處初始化一次,而且是常駐記憶體的。因此,當我們希望一個變數在程式的整個生命週期記憶體在,但是僅在區域性可見時,就用到static關鍵字了。請注意,我們講的是函式呼叫處,也就是說,如果一個static變數被定義在函式func()中:
int func() {
static int s_intValue = 0;
s_intValue ++;
return s_intValue;
}
但是,如果上面程式碼中的func()函式在程式整個生命週期內沒有被呼叫過,那麼該s_intValue的static變數也就從來沒有在記憶體中存在過,更沒有初始化過。
實際上,在多執行緒環境中,程式設計將變得複雜起來。我們為了保證程式在多執行緒時可以正常執行,通常會使用資料鎖來保護變數。但是如果把這個變數定義在靜態物件的類內部,就可能出現問題。比如:
// class.h
CMutex g_mtx;// CMutex為某種資料鎖。比如QMutex。此處我們不做過多討論。
class CMyClass {
static CMyClass& instance() {
g_mtx.lock();
static CMyClass s_staticObj;
g_mtx.unlock();
return s_staticObj;
}
public:
~CMyClass(){}
private:
CMyClass(){}
};
比如,上述程式碼中是一個單體類的簡單實現,在instance()介面中,如果不使用全域性鎖進行保護,那麼在多執行緒環境下(低版本的編譯器中),有可能造成該介面多次重入時s_staticObj變數多次初始化的現象,這是非常奇怪的,因為按照static關鍵字的語法,使用static定義的變數應該有且僅有一次初始化過程,但是小編卻經歷過存在多次初始化過程的static變數。這很有可能跟編譯器及其特定版本有關。
靜態物件的解構函式一般是在main()函式退出或者exit()被呼叫時才呼叫,因此在靜態物件的解構函式中呼叫exit()將導致死迴圈。這點是我們需要注意的。靜態物件的析構順序是按它們構造的順序相反進行的,這點可以由編譯器保證。
本文開頭提到過,extern變數可以被全域性作用域訪問,如果希望一個變數僅在某個檔案內可見,就可以使用static關鍵字,它可以保證該變數僅在該檔案內可見。
結語:
----------------------------------------------------------------------------
static關鍵字在定義常駐記憶體的變數時經常會被使用,它也被用來實現單體類定義。當然,現在有很多第三方庫提供了單體類模板的支援,已經使程式設計變得簡單多了。希望static在大家的軟體開發過程中發揮更大的作用。
如果您喜歡本文歡迎轉發。也可關注本人的微信公眾號。
參考資料
----------------------------------------------------------------------------
《C++程式設計思想》兩卷合訂本中文版(10.1章節),(美) Bruce Eckel Chuck Allison著