我已经习惯了全局/静态类成员的所有初始化的思想作为主要的第一行()之前发生的事情。 但最近我读的地方,该标准允许初始化以后发生在“协助模块动态加载。” 我可以看到这是真的时动态链接:我不希望在库初始化的全局之前,我dlopen'ed库进行初始化。 然而,静态链接在一起翻译单元(我的应用程序的直接.o文件)的组内我会觉得这种行为非常不直观。 这是否只发生在懒洋洋地动态链接或者它可以发生在任何时候? (或者是我刚刚读错了;)
Answer 1:
该标准在3.6.2 / 3的情况如下:
它是实现定义的命名空间范围的对象的动态初始化(8.5,9.4,12.1,12.6.1)是否被主的第一条语句之前完成。 如果初始化的主要的第一条语句后推迟到某个时间点,应首先使用在相同的翻译单元定义为对象进行初始化任何功能或对象之前发生。
但是,哦,当然,你可以从未正式告诉当初始化发生以来初始化您访问变量之前会发生! 如下:
// t1.cc
#include <iostream>
int i1 = 0;
int main () {
std::cout << i1 << std::endl
// t2.cc
extern int i1;
int i2 = ++i1;
我可以符合使g ++ 4.2.4至少出现之前主要执行“I2”的初始化。
Answer 2:
一个想与规则来解决的问题是动态加载的一个。 这种补贴不仅限于动态加载和正式可能发生的其他案件。 我不知道该用它来做什么比动态加载其他的实现。
Answer 3:
让我们回顾一下伪代码:
在DLL:
static int ItsDllVar = 1;
int EXPORTED_FUNCTION() { return ItsDllVar; }
在应用程序:
static int AppVar1 = 2;
static int AppVar2 = EXPORTED_FUNCTION() + AppVar1;
所以根据静态初始化AppVar2得到1 + 2 = 3
适用于局部静态变量的初始化工作(无论DLL的)
int f()
{
static int local_i = 5;//it get's 5 only after visiting f()
return local_i;
}
Answer 4:
我觉得这是我的情况与G ++ 4.7和CMake的(不知道这是关于CMake的相关细节)发生了什么事。 我有一个注册在工厂函数的记号。 它依赖于构造从全局初始化的变量调用。
当这个代码是在静态链接库中的初始化没有发生! 这是现在的工作很好,当我把它移动到直接链接的目标文件(即,它们不是合并成一个库第一)。
所以,我怀疑你是正确的。
文章来源: How lazy can C++ global initialization be?