先进后出原则,最先初始化的最后析构!
1.C++中全局对象、变量的构造函数调用顺序是跟声明有一定关系的,即在同一个文件中先声明的先调用。对于不同文件中的全局对象、变量,它们的构造函数调用顺序是未定义的,取决于具体的编译器
2.C++总是按成员变量在类声明中出现的顺序来初始化成员变量的,为什么C++不按初始化列表的顺序来初始化成员变量呢?因为我们知道初始化的顺序应该与析构的顺序相反,而对一个类来说 constructor 可能有多个,初始化列表也会有多个,所以C++就选择了简单的点的方法,按成员变量出现的顺序来初始化。
3.基类的静态变量先初始化,然后是它的派生类。直到所有的静态变量都被初始化。这里需要注意全局变量和静态变量的初始化是不分次序的。这也不难理解,其实静态变量和全局变量都被放在公共内存区。可以把静态变量理解为带有“作用域”的全局变量
顺序为: 1基类的静态变量或全局变量 2派生类的静态变量或全局变量 3基类的成员变量 4派生类的成员变量
#pragama init_seg 预处理器指令
C++标准中,处于同一编译单元(cpp)的全局对象按其声明次序初始化并倒序析构,但标准中没有说处于不同编译单元的全局对象的初始化顺序。这带来了很多问题。
假如有个Log对象负责程序日志的记录。如果程序结束时,有某个全局对象出现类似于资源释放失败的错误,该对象会调用Log记录错误,这时,Log可能已经被销毁了…… 这就是所谓的dead-reference问题。
pragma init_seg(compiler) #pragma init_seg(lib) #pragma init_seg(user) #pragma init_seg("user_defined_segment_name")
init_seg 预处理器指令: 编译器、 库、 用户,和"user_defined_segment_name
前三个指令,初始化优先次序依次降低,但都先于普通的全局变量构造,如cout就是使用compiler级别构造的
注:一个源文件只能出现一次init_seg 指令
pragma init_seg(compiler)是保留给微软 C/C++ 运行库使用的,我们不应该使用它!
在我们自己的代码里,如果希望一些对象先于其他对象初始化,我们可以使用 #pragma init_seg(lib) 指令
// file2.cpp // command line: cl /c file2.cpp #pragma init_seg(lib) #include<iostream.h> class MyLibClass
还是不要在库中用#pragma init_seg(lib), 不然 warning C4073: 初始值设定项放置在库初始化区域中,然后挂掉了!!
还是用#pragma init_seg(user)吧