7

一旦我正在阅读一个非常棒的C++常见问题解答(它真的很棒!! https://isocpp.org/faq)并阅读了有关如何防止静态初始化顺序“失败”的主题。所以作者建议将静态变量包含到函数中,从而通过维护变量的创建顺序来防止“失败”。但这在我看来似乎是一个粗鲁的解决方法。所以我的问题是,是否有任何现代的,更模式化的方式来防止这种“惨败”,而是将“静态的东西”封装到函数中?防止静态初始化顺序“失败”,C++

+4

防止失败的优雅方法是永远不要使用依赖于任何东西的静态对象。 – user2079303

+0

常见问题解答建议*建立在首次使用习语*上。对许多C++程序员来说,它是一种类似的模式。实施起来很简单,甚至更简单。我看不出“现代,更多以模式为导向”的意思。 –

+0

另请参阅[AddressSanitizerInitializationOrderFiasco](https://github.com/google/sanitizers/wiki/AddressSanitizerInitializationOrderFiasco)。 – jww

回答

8

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

没有其他解决方法。

这不会是一个“失败”,否则!

+0

不幸的是,这是不现实的。它不能帮助典型的回购或GNU的FTP站点中的数千个软件包。 – jww

+0

@jww:唯一合理的选择是做OP本身在问题中提出的建议。 –

+0

这是一个错误的选择。它将解决问题,以便在崩溃时遇到崩溃;而不是一个构造函数。当物体过早消失时,我已经经历了第一手的崩溃。 – jww

1

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

然后按需要的顺序构建对象。例如,如果我们有两个对象的x和y,和y的结构,如果x没有构成将失败,则第一构造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; 
} 

但是,如果可能的话,最好避免使用静力学。

2

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

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

在实践中,您可能会遇到需要静态数据的情况。如果与其他静态数据不存在依赖关系,则使用静态数据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。作为一个经验法则,如果你有很多的第二和第三种情况,你没有做足够的第一个。