C/C++之全局、static對象/變量的初始化問題

關於全局、static對象/變量的初始化問題
1. 全局變量、static變量的初始化時機:main()函數執行以前(或者說main中第一個用戶語句執行以前)。
2. 初始化順序
1)全局對象、外部static對象
    a)同一編譯單元(同一源文件)中,按照對象/變量的定義順序初始化。
    b)不一樣編譯單元,C++標準未保證初始化前後順序,只保證都在main()以前初始化完成。
2)函數內部local static變量,在該函數調用過程當中第一次遇到該static變量時初始化。
 
     基於以上觀點,大師們建議少用全局變量,全局變量之間要消除依賴關係——特別是初始化依賴關係!
     全局變量的使用能夠參考  Scott Meyers  在《More Effective C++》中M34所說的,模擬Singleton模式,經過函數內部的local static變量來代替全局變量。
     寫個示例程序驗證下這些變量的初始化,中間的註釋部分就做爲上面結論的一些補充吧。

class CA
{
public:
     class CInner
     {
     public:
          CInner()
          {
               cout << "constructor of inner class CInner." << endl << endl;
          }
     };
public:
     CA()
     {
          cout << "Constructor of CA." << endl;
          cout << " m_i1 = "  << m_i1
                  << ", m_i2 = " << m_i2
                  << ", m_i3 = " << m_i3
                  << ", m_i4 = " << m_i4 << endl << endl;
     }
     static void Func1()
     {
          cout << " In function Func1()." << endl;
          static CInner myInner1;
     }
     static void Func2()
     {
          cout << " In function Func2(), m_i1 = " << m_i1 << endl;
          if(m_i1 < 10)
          {
               cout << "m_i1 < 10 and Constructor of CInner won't be called!" << endl << endl;
               return;
          }
          static CInner myInner2;
     }
public:
     static int m_i1;
     static int m_i2;
     static const int m_i3;
     static int m_i4;
};
/* 不一樣模塊的全局、static變量/對象初始化順序不肯定;
 * 同一個編譯模塊按定義順序初始化。
 * 但有一點相同,就是它們均在編譯期已分配好內存。
 * 對於諸如基本數據類型,編譯期能肯定其值的,編譯器就直接將值寫入分配的空間,如「CA::m_i1=3"。
 * 對於編譯期不能肯定值的,要等到運行時main函數以前初始化,如theCA、CA::m_i2。
 * 但若static的初始化表達式均爲const或字面常量等肯定的值,則亦能在編譯期肯定值,如m_i4。
 */

int CA::m_i1 = 1;
CA theCA;
const int  CA::m_i3 = 3;
int CA::m_i2 = CA::m_i1 + 1;
int CA::m_i4 = CA::m_i3 + 1;
int main(int argc, _TCHAR* argv[])
{
     CA::Func1();
     CA::Func2();
     cout << "After CA::m_i1 increased by 11 :" << endl;
     CA::m_i1 += 11;
     CA::Func2();
     return 0;
}

以上程序運行結果爲:
Constructor of CA.
 m_i1 = 1, m_i2 = 0, m_i3 = 3, m_i4 = 4
 In function Func1().
constructor of inner class CInner
 In function Func2(), m_i1 = 1
m_i1 < 10 and Constructor of CInner won't be called!
After CA::m_i1 increased by 11 :  In function Func2(), m_i1 = 12 constructor of inner class CInner.
相關文章
相關標籤/搜索