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.