static initialization
静态初始化,只适用于拥有静态存储期(static storage duration)的变量。拥有静态存储期的变量是:
All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern.
举例:
int i;
void f(){
static int j;
}
拥有静态存储期的变量,在程序运行之前就分配了空间。更确切的说,是在编译成目标文件或者把可执行文件装载到内存中的时候分配的空间。
什么是静态初始化呢?
静态初始化,指的是在程序开始运行之前,就对变量进行了初始化。
静态初始化包含两种情况,zero initialization和constant initialization。
int a; // zero initialization
int b = 1; // constant initialization
zero initialization指的是初始化为0,constant initialization指的是初始化为常量表达式的值。
造成这两种初始化的区别的根本原因是,具有静态存储期的变量的存储位置不同。
众所周知,具有静态存储期的变量(不考虑const)存储在data段和bss段。其中data段存储的是,用常量表达式初始化的变量;bss段存储的是没有常量表达式来初始化的变量。
- data段里面的是constant initialization的变量。在编译的时候,变量就被分配了文件空间,就被初始化好了。
- bss里面的是未初始化的变量。在编译的时候bss段是没有实际占用文件空间的,而是在装载的时候才进行分配空间然后全部初始化为0。所以bss里面的变量也就是会进行zero initialization的变量。
总结来说, static initialization只是针对static storage duration的变量的概念,分为zero initialization和constant initialization。
dynamic initialization
相对的概念,除了静态初始化之外的全部都是动态初始化。
首先,非静态存储期的变量都是动态初始化。例如:
void f(){
int i = 0;
}
其次,静态存储期的变量也有可能动态初始化。例如:
struct T{
int i;
T(int ii) : i(ii) { }
};
T t(0); // dynamic
int i = f(); // dynamic
void g(){
static T t(0); // dynamic
}
但是上面是的过程就不是单纯的动态初始化,而是静态初始化和动态初始化的结合。首先装载时给变量分配地址空间,进行zero initialization,然后程序运行时再调用(构造)函数进行dynamic initialization。
补充
具有静态存储期的变量一般都是存在data段和bss段,但是const修饰的变量是例外。const 修饰的变量和一些字符串字面量在rodata段或者text段,这取决于编译器的实现。对于gcc编译器而言,这些变量在text段。
对于静态初始化,如果constant initialization的常量表达式是0的话,那么编译器一般将其视为zero initialization,即变量在bss段而非data段。这样做有助于减小可执行文件的大小。
例子:
int a; // bss segment
int b = 1; // data segment
int c = 0; // bss segment
const int d = 0; // text segment