摘要:
保持顺序,不同编译单元中的名字空间级对象决不应该在初始化上互相依赖,因为其初始化顺序是未定义的。这样做会惹出很多麻烦,轻则在项目中稍做修改就会引发奇怪的崩溃,重则出现严重的不可移植问题——即使是同一编译器的新版本也不行。
在不同的编译单元中定义两个名字空间级的对象时,先调用哪一个对象的构造函数是没有定义的。经常工具可能会碰巧按照编译单元目标文件的连接顺序初始化,但这种假设并不总是可靠的;即使确实如此,你总不会希望自己的代码的正确性难以捉摸地依赖于makefile或者项目文件吧。
因此,在任何名字空间级对象的初始化代码中,不能假设其他编译单元中定义的任何其他对象都已经初始化了。这些考虑方法也适用于动态初始化的原始类型变量。
请注意,甚至在使用构造函数构造之前,名字空间级对象就已经使用0静态初始化过了。有些自相矛盾的是,这种零初始化会使错误更难以检查,因为静态的零初始化不会迅速使程序崩溃,而是使未初始化对象显现出一种看似合理的表象。你可能认为字符串是空的,指针是空的,整数型变量为0,而事实上,代码已经费劲地将它们初始化了。
为了避免这一问题,应该尽可能地避免使用名字空间级的变量,它们很危险。如果确实需要可能依赖于另一个变量的此种变量,可以考虑使用singleton设计模式。使用时要小心一些,可以通过确保对象在第一次访问时被初始化,来避免隐含的依赖性。Singleton本质上也是全局变量,它会因为相互依赖或者循环依赖而被破坏。