C++: 全局变量和static变量初始化问题
1. 初始化时机
全局变量、文件域中的静态变量、类中的成员静态变量在main函数执行前初始化;局部变量中的静态变量在第一次调用时初始化。
C和C++的区别:局部静态变量:
在C语言中是编译期初始化并分配内存,故不能用变量给静态局部变量赋值,只能用常量。
在C++中是第一次执行时初始化,因为C++引入了对象的概念,对象一般需要构造函数,无法简单的分配内存,故可以用变量赋值,并且在第一次使用时初始化。
初始化又分为静态和动态:
静态初始化:
针对用常量来对全局变量进行初始化的情况,这个变量是简单的内置类型(不包括含构造函数的复杂类,归属于下一项)。例如这里的a变量。
int a = 3; class A{ };
在程序加载过程中完成。
根据变量是否设置初值分别放于data segment段(设置初值)和bss段(未设置初值)
动态初始化(运行期)(main函数前,局部静态变量除外):
1. 需要经过函数调用来完成的初始化。例如这里的a变量。
int a = foo()
2. 复杂类型的初始化。需要调用构造函数。例如这里的aa变量。
Class A{
A(){}
}
A aa;
静态初始化的时机是先于动态初始化的。
1)类的静态成员变量声明和定义
使用过类中的静态成员变量的伙伴都发现了,在类中定义的静态成员变量,还必须要在类外定义下才可以使用,否则会编译报错。
那么为什么会出现这种情况呢?
静态成员变量不属于任何一个对象,对象的数据中不应该包含静态成员的数据。所以在定义类的时候不会给静态变量分配内存只是声明,因此就要在其他地方分配即定义。
定义与声明的区别:
声明:只是向程序表面变量的类型和名字。
定义:为变量分配内存,也可以顺便初始化。程序中变量有且只有一个定义(更能说明为什么要在类外再定义下类的静态成员变量了)。
2. 初始化顺序
对于编译单元(同一个文件)的全局变量来讲,初始化顺序跟声明的顺序一致。销毁顺序则相反。
对于不同编译单元的全局变量,初始化顺序不确定。对于不同编译单元的全局变量互相引用的情况应避免。
3. 解决不同文件相互引用全局变量初始化顺序不确定问题
1)可以通过函数调用,引用的时候不直接引用全局变量,而是放在一个函数中。函数中的全局变量在调用时初始化。
int get_a() {
static int a = 5;
return a; } int get_b() {
static int b = get_a();
return b; }