该标准明确规定静态持续时间变量(命名空间范围和类静态成员)的动态初始化不必在执行main之前发生: “无论命名空间作用域对象的动态初始化(8.5,9.4,12.1,12.6.1)是否在main的第一个语句之前完成,它都是实现定义的。” IS 3.6.2(3) 是不是[实施?]实现了动态初始化的方式?有什么更好/更简单的方法可以保证在使用前初始化对象?
答案 0 :(得分:4)
你的问题的答案在你引用的那一句之后的下一句话(在ISO / IEC 14882-2003的3.6.2中)。
是否是实现定义 或不是动态初始化 对象的(8.5,9.4,12.1,12.6.1) 命名空间范围是在之前完成的 主要的第一个声明。 如果 初始化推迟到一些 第一次之后的时间点 主要陈述,应该发生 在第一次使用任何功能之前 或在其中定义的对象 翻译单位作为对象 初始化。强>
显然,要确保初始化某个变量X
,您只需在函数main
中(直接或间接)使用与变量{{1相同的转换单元中定义的任何函数或变量(例如,如果您在函数X
中直接或间接使用X
,那么您可能确定它已经初始化了。)
答案 1 :(得分:4)
我认为这里的意图是允许动态加载库。
库中定义的静态变量不保证在main之前初始化,但必须在使用特定库中的任何内容之前进行。
答案 2 :(得分:2)
这不是一个直接的答案,但为了比较一下类似的语言(Ada)如何处理同样的情况,这可能是有趣的。
在Ada包中(粗略等同于命名空间)可以包含初始化数据,这些数据实际上与程序具有相同的生命周期,就像Cish静态一样(为简单起见,我们将忽略通用包,它们可以在较低范围内创建模板)。执行这些初始化的过程称为“精化”。
Ada保证在主程序开始时详细说明所有包裹。但是,如果还没有详细说明另一个包,那么很有可能创建“精心制作”的代码。通常,编译器会选择精化顺序。因此编写除非编译器恰好选择您需要的顺序之外无法工作的代码被视为“有界错误”。
显然这并不理想,因为通常需要在其他包中使用非内置数据类型,有时这将包括一些需要详细说明的初始化。因此,Ada提供了一些pragma
,允许您在当前包之前要求编译器详细说明您的部分或全部依赖项。
这不完美。编写实际上没有有效精化顺序的代码是完全可能的。如果你这样做(或者没有得到编译指示的权利而且编译器也无法解决它),那么在详细说明期间会出现Program_Error
异常。有些调试器无法单步执行精化代码,因此这些错误可能是要追踪的主要PITA。尽管如此,我真的很想念C ++中的这个功能。如果你小心的话,能够在“静态”声明中使用复杂对象,并且必须完全避免它们之间的区别。
答案 3 :(得分:1)
静态持续时间变量(命名空间范围和类静态成员)的动态初始化始终在执行main之前发生。
未定义这些静态持续时间变量初始化的顺序。