關於全局、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.