防止静态初始化命令" fiasco",C ++

时间:2015-04-23 11:32:20

标签: c++ static wrapping static-initialization static-order-fiasco

一旦我读了一篇很棒的C++ FAQ(这真的很棒!!)并阅读了topic关于如何防止静态初始化命令" fiasco"。因此作者建议将静态变量包装到函数中,从而防止" fiasco"通过维护变量的创建顺序。但在我看来,这是一个粗鲁的解决方法。所以我的问题是,是否有任何现代的,更加模式化的方式来防止这种惨败"但要包装"静态东西"进入功能???

3 个答案:

答案 0 :(得分:12)

现代的,更注重模式的方式是不首先使用全局变量

没有别的办法了。

它不会成为"惨败"否则!

答案 1 :(得分:2)

  

所以我的问题是,是否有任何现代的,更多模式导向的方法来防止这种“惨败”,但将“静态东西”包装成函数???

在大多数情况下,您可以在main函数中声明“全局”数据,并在需要时使用依赖注入来传递它。换句话说,根本没有静态。

实际上,您可能会遇到需要静态数据的情况。如果没有其他静态的依赖项,请创建静态数据const/constexpr

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

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

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

总结:

大多数(90%?99%?)静态/全局/共享数据应该依赖注入到它的使用位置,而不是根据静态创建。

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

非常罕见的情况下,当静态需要是静态的并且它们相互依赖时,用静态方法对它们进行wap。

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

答案 2 :(得分:1)

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

然后按所需顺序构造对象。例如,如果我们有两个对象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;
}

但是,实际上,如果可能的话,最好避免使用静态。