防止静态初始化顺序"fiasco",C++

Prevent static initialization order "fiasco", C++

有一次我读到一篇很棒的文章 C++ FAQ (It is really good!!) and read the topic 关于如何防止静态初始化顺序 "fiasco"。所以作者建议将静态变量包装到函数中,通过维护变量的创建顺序来防止"fiasco"。但这在我看来是一个粗鲁的解决方法。所以我的问题是,是否有任何现代的、更面向模式的方法来防止这种 "fiasco" 但将 "static stuff" 包装到函数中???

现代的、更面向模式的方法是首先不要使用全局变量

别无他法。

不会是"fiasco",否则!

解决该问题的更常用方法是尽可能避免静态 - 在依赖构造顺序的对象之间更是如此。

然后按照要求的顺序构造对象。例如,如果我们有两个对象 x 和 y,如果 x 没有被构造,y 的构造将失败,那么先构造 x 并将其提供给 y)

的构造函数(或另一个成员)
 SomeObject x;
 SomeOtherObject y(x);

 SomeObject *x = new SomeObject;
 SomeOtherObject y = new SomeObject(*x);   

(以上均假设y的构造函数需要引用)。

如果您需要在函数之间共享 xy,只需将它们作为参数传递给函数即可。

如果你必须使用静态(即你不想在任何地方输入传递参数)使静态成为指针,并初始化它们一次(例如,在 main() 中)。

//  all source files can use x and y via these declarations  (e.g. via a header file)

extern SomeObject *x;
extern SomeOtherObject *y;

//  definition in one source file only

SomeObject *x;
SomeOtherObject *y;

int main()
{
     x = new SomeObject;
     y = new SomeOtherObject(*x);

       // call other functions that use x and y.

     delete y;
     delete x;
}

但是,实际上,最好尽可能避免使用静力学。

So my question is, is there any modern, more pattern oriented way to prevent this "fiasco" but to wrap the "static stuff" into functions???

在大多数情况下,您可以在主函数中声明您的 "global" 数据,并在需要时使用依赖注入来传递它。也就是说,完全没有静态。

在实践中,您可能会遇到需要静态数据的情况。如果没有对其他静态的依赖,使静态数据const/constexpr.

// smart pointer that implements the "Foo" release policy
class FooPointer
{
    static const FooPointer NullFoo; // does not depend on other static values
    /* ... */
};

如果静态变量 do 相互依赖,只需将它们包装在静态函数中即可:

// smart pointer that implements the "Foo" release policy
class FooPointer
{
    static const FooPointer& NullFoo(); // depends on other static values
    /* ... */
};

总结:

大多数(90%?99%?)static/global/shared 数据应该依赖注入到使用它的地方,而不是创建为静态数据。

在极少数情况下,当出于某种原因需要静态变量并且它们不依赖于其他静态变量时,请声明静态变量。

非常极少数情况下,当静态需要静态并且它们相互依赖时,将它们转换为静态方法。

根据经验,如果您有很多第二种和第三种情况,那么您在第一种情况下做得还不够。