全局对象的构造和析构
- _init() 函数先于main函数调用,_fini() 后于main函数调用;
- _init() 函数中会对全局对象进行构造,_fini() 对全局对象进行析构;
- 编译器对每一个编译单元进行编译是,若检测到该编译单元中有实现了构造函数的全局对象,则会合成一个全局对象构造函数GLOBAL_VAR_INIT(),用来对全局变量进行初始化;该函数指针被放在该编译单元的.ctor段内;同时,若对象声明了析构函数,还会注册全局析构函数;
- 链接器链接时,将编译单元中的同名段进行合并,于是所有包含全局对象的编译单元中的所有.ctor段就被合并成了一个函数指针数组;
- _init() 函数遍历.ctor中的全局构造函数数组,对所有的全局对象进行初始化;
- _fini() 中,按照先构造后析构的顺序,对全局对象进行析构;
- 全局对象在.ctor中的构造顺序与编译顺序有关;
- 全局对象的构造函数和析构函数不应依赖于另一个全局/静态对象; 全局对象A构造时,全局对象B可能还未构造,只是被分配了内存,数据成员未定义;同样,全局对象A析构时,全局对象C可能已经析构,若A的析构函数对全局对象C进行访问,行为也是未定义的;
- 【另】编译顺序也会影响内联函数的展开结果;
示例及伪代码
class HelloWorld
{
public:
HelloWorld(){};
~HelloWorld(){};
};
HellowWorld gHw;
static void GLOBAL_VAR_INIT()
{
// 构造全局对象
gHw.HellowWorld::HellowWorld();
// 为全局对象注册析构函数
atexit(__tcf_l);
}
int main()
{
return 0;
}
.ctor:
__CTOR_LIST__; // 全局对象构造函数的函数指针数组
/// 该函数在main之前执行
_init()
{
for (ctor in __CTOR_LIST_)
{
ctor();
}
}