1. 程式人生 > >C++老鳥日記033  static兩種基本含義

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著