C++ 静态变量的动态初始化阶段

C++ 静态变量的动态初始化阶段,c++,C++,该标准明确规定,在执行main之前,不必对静态持续时间变量(命名空间范围和类静态成员)进行动态初始化: “命名空间范围的对象的动态初始化(8.5、9.4、12.1、12.6.1)是否在main的第一个语句之前完成是由实现定义的。”is 3.6.2(3) 这不是动态初始化[始终?]的实现方式吗?有什么更好/更简单的方法来保证对象在使用前已初始化 静态持续时间变量(命名空间范围和类静态成员)的动态初始化总是在执行main之前进行。 这些静态持续时间变量的初始化顺序没有定义。这不是一个直接的答案,但为

该标准明确规定,在执行main之前,不必对静态持续时间变量(命名空间范围和类静态成员)进行动态初始化: “命名空间范围的对象的动态初始化(8.5、9.4、12.1、12.6.1)是否在main的第一个语句之前完成是由实现定义的。”is 3.6.2(3)
这不是动态初始化[始终?]的实现方式吗?有什么更好/更简单的方法来保证对象在使用前已初始化

静态持续时间变量(命名空间范围和类静态成员)的动态初始化总是在执行main之前进行。

这些静态持续时间变量的初始化顺序没有定义。

这不是一个直接的答案,但为了便于比较,我们可能需要了解类似语言(Ada)如何处理相同的情况

在Ada包(大致相当于名称空间)中,可以有与程序具有相同生命周期的初始化数据,这与Cish静态非常相似(为简单起见,我们将忽略通用包,它与可在较低范围内创建的模板类似)。进行这些初始化的过程称为“精化”

Ada保证在主例程开始时对所有包进行详细说明。然而,创建“精化”代码是很有可能的,如果另一个包还没有被精化,它将不起作用。通常,编译器会选择精化顺序。因此,除非编译器碰巧选择了所需的顺序,否则编写的代码将无法工作,这被视为“有界错误”

显然,这并不理想,因为在其他包中使用非内置数据类型通常是可取的,有时这将包括一些需要详细说明的初始化。因此,Ada提供了一些
pragma
s,允许您在当前包之前要求编译器详细说明一些或所有依赖项


这并不完美。编写没有有效细化顺序的代码是很有可能的。如果您这样做(或者没有正确使用pragma,编译器也无法理解),您将在精化过程中遇到一个
Program\u错误
异常。一些调试器在处理精化代码时遇到困难,因此这些错误可能是需要跟踪的主要PITA。不过,我真的很怀念C++中的这个设备。如果小心的话,在“静态”声明中使用复杂对象与完全避免复杂对象之间是有区别的。

您的问题的答案在您引用的下一句话(ISO/IEC 14882-2003的3.6.2)中

它是由实现定义的 或者不是动态初始化 (8.5、9.4、12.1、12.6.1)对象的 在 主要问题的第一项声明如果 初始化延迟到某个时间 第一次之后的时间点 主要的声明,它应该发生 在首次使用任何函数之前 或在同一文件中定义的对象 翻译单位作为被翻译对象 已初始化。

显然,为了确保某个变量
X
已初始化,您只需在函数
main
(直接或间接)中使用与变量
X
定义在同一转换单元中的任何函数或变量即可(例如,如果您在函数
main
中直接或间接使用
X
,则可以确保它已初始化)

编辑:

如果除了保证您使用的变量已经初始化之外(它始终是——正如上面引用的标准文本所保证的那样),您还想知道为什么标准包含在
main
执行开始后可能延迟初始化的规定

我的意思是,如果问题是:为什么不要求在
main
启动之前执行所有初始化

这肯定不是动态链接库——在开始<代码>主< /代码>之前初始化所有对象都没有问题。它也不是关于动态加载的库(<代码> LoadLibrary <代码> />代码> dLoOb/COD>)——它们显然不在C++标准的范围内。(例如,它们不受一个定义规则的约束,通常它们甚至可能不是C++)

理论上,此规定允许延迟初始化以避免不必要的运行时开销,例如,除非您实际使用特定翻译单元(C++源文件)中的某些函数或对象您不必执行其运行时初始化,但任何实现都不太可能在运行时执行延迟初始化-多线程同步对于此类初始化来说是一项挑战,而且本身就是一项运行时开销


但是每个实现实际做的是只链接那些实际使用的模块(翻译单元)。因此,即使你链接到一些静态库,其中包含一些动态初始化的对象(可能有副作用,如文件创建或用户交互)但是不要使用来自同一翻译单元的任何东西-实现根本不必运行此对象的初始化。因此,此规定允许避免在最终可执行文件中包含任何未使用的翻译单元-即使它们是程序的正式部分。

我相信这里的目的是允许动态加载库


库中定义的静态变量不能保证在main之前初始化,但必须在使用特定库中的任何内容之前初始化。

您在哪里读到的?我不确定这是真的。您可能会想到“静态初始化顺序失败”(Static initialization order faisco),但这与
main()无关请参阅我的编辑:ISI的3.62(3)不知道C++标准所说的,但至少在C中“静态初始化的方式和时间”