C++ 标准第 3.6.2 节第 3 段指出,非本地对象的动态初始化是否发生在 main() 的第一条语句之后是实现定义的。
有谁知道这是什么原理,哪些编译器会以这种方式推迟非本地对象初始化?我最熟悉 g++,它在输入 main() 之前执行这些初始化。
这个问题是相关的:静态变量的动态初始化阶段 但我特意问的是已知哪些编译器会以这种方式运行。
这一段的唯一理由可能是支持在运行时加载的动态库,但我认为该标准没有考虑动态加载问题。
C++ 标准第 3.6.2 节第 3 段指出,非本地对象的动态初始化是否发生在 main() 的第一条语句之后是实现定义的。
有谁知道这是什么原理,哪些编译器会以这种方式推迟非本地对象初始化?我最熟悉 g++,它在输入 main() 之前执行这些初始化。
这个问题是相关的:静态变量的动态初始化阶段 但我特意问的是已知哪些编译器会以这种方式运行。
这一段的唯一理由可能是支持在运行时加载的动态库,但我认为该标准没有考虑动态加载问题。
原因之一可能是:
static char data[1000000000000000000000000000000];
void main(int argc)
{
if (argc > 0)
data[0] = 0;
}
只有当事实证明确实需要它时才分配和初始化这个静态数组可能是合理的。某些申请可能会遇到类似的情况,并且有足够的发言权来说服委员会。根据我自己使用 C# 的经验,我遇到了在 jitting 类后没有立即分配类的静态成员的情况。在第一次使用时,它们被一个一个地分配。在那种情况下,绝对没有理由这样做。这简直是一场灾难。也许他们现在解决了这个问题。
其他原因也是可能的。
来自 C++11 草案:
具有静态存储持续时间的非局部变量的动态初始化是否在 main 的第一条语句之前完成是实现定义的。如果初始化延迟到 main 的第一个语句之后的某个时间点,它应该发生在与要初始化的变量在同一翻译单元中定义的任何函数或变量的第一次 odr-use (3.2)之前。[强调我的]
也就是说,必须在使用同一翻译单元中定义的任何内容之前初始化静态变量。
在我看来,这样做是为了允许动态库(DLL 或 SO)被延迟加载和初始化,甚至动态地(调用dlopen
或LoadLibrary
其他)。很明显,在 DLL 本身加载之前,无法初始化 DLL 中定义的变量。
自然,C++ 对 DLL 一无所知,因此标准中没有直接提及它们。但是委员会的人确实知道真实的环境和编译器,当然也知道 DLL。如果没有这个子句,延迟加载 DLL 在技术上会违反 C++ 规范。(并不是说它会阻止实现者这样做,但是如果我们都尝试彼此配合会更好。)
关于哪些系统支持这一点,据我所知,至少 MS Visual C++ 编译器支持惰性动态链接(DLL 甚至在第一次使用之前不会被加载)。大多数现代平台都支持动态加载 DLL。