防止静态初始化顺序"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
的构造函数需要引用)。
如果您需要在函数之间共享 x
和 y
,只需将它们作为参数传递给函数即可。
如果你必须使用静态(即你不想在任何地方输入传递参数)使静态成为指针,并初始化它们一次(例如,在 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 数据应该依赖注入到使用它的地方,而不是创建为静态数据。
在极少数情况下,当出于某种原因需要静态变量并且它们不依赖于其他静态变量时,请声明静态变量。
在非常极少数情况下,当静态需要静态并且它们相互依赖时,将它们转换为静态方法。
根据经验,如果您有很多第二种和第三种情况,那么您在第一种情况下做得还不够。
有一次我读到一篇很棒的文章 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
的构造函数需要引用)。
如果您需要在函数之间共享 x
和 y
,只需将它们作为参数传递给函数即可。
如果你必须使用静态(即你不想在任何地方输入传递参数)使静态成为指针,并初始化它们一次(例如,在 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 数据应该依赖注入到使用它的地方,而不是创建为静态数据。
在极少数情况下,当出于某种原因需要静态变量并且它们不依赖于其他静态变量时,请声明静态变量。
在非常极少数情况下,当静态需要静态并且它们相互依赖时,将它们转换为静态方法。
根据经验,如果您有很多第二种和第三种情况,那么您在第一种情况下做得还不够。