该标准明确规定静态持续时间变量(命名空间范围和类静态成员)的动态初始化不必在执行main之前发生:"无论动态初始化是否为实现定义(8.5,9.4,12.1,12.6. 1)命名空间作用域的对象是在main的第一个语句之前完成的." IS 3.6.2(3)不是如何实现动态初始化[总是?]?有什么更好/更简单的方法可以保证在使用前初始化对象?
您的问题的答案在您引用的句子之后的下一句(在 ISO/IEC 14882-2003 的 3.6.2 中)。
命名空间范围的对象的动态初始化(8.5、9.4、12.1、12.6.1)是否在main的第一条语句之前完成由实现定义。如果初始化推迟到 main 的第一条语句之后的某个时间点,则它应在第一次使用与要初始化的对象在同一翻译单元中定义的任何函数或对象之前发生。
显然,要确保X初始化某些变量,您只需要在函数中main(直接或间接地)使用在与变量相同的翻译单元中定义的任何函数或变量X(例如,如果您直接或间接地X在函数中使用,main那么您可以确定它已经初始化)。
编辑:
如果除了保证您使用的变量已经初始化(它总是 - 正如上面引用的标准文本所保证的那样),您还想知道为什么标准包含初始化可能会延迟的规定 main执行开始。
我的意思是如果问题也是:为什么不要求在main开始之前执行所有初始化?
嗯,这绝对不是关于动态链接的库——在开始之前初始化它们的所有对象没有问题main。此外,它与动态加载的库 ( LoadLibrary/ dlopen) 无关 - 它们显然不在 C++ 标准的范围内(例如,它们不受单一定义规则的约束,通常它们甚至可能不是 C++)。
理论上,此条款允许延迟初始化以避免不必要的运行时开销——例如,除非您实际使用来自特定翻译单元(C++ 源文件)的某些函数或对象,否则您不必执行其运行时初始化。但是,任何实现都不太可能在运行时真正进行延迟初始化——多线程同步对于这种初始化来说具有挑战性,并且本身就是运行时开销。
但是每个单独的实现实际上所做的只是链接那些实际使用的模块(翻译单元)。因此,即使您链接到一些包含一些动态初始化对象的静态库(可能有副作用 - 如文件创建或用户交互)但不使用来自同一翻译单元的任何内容 - 实现没有义务运行此对象的初始化根本。因此,该条款允许避免在最终可执行文件中包含任何未使用的翻译单元——即使它们正式成为程序的一部分。