[英]C++ static initialization order
当我在 C++ 中使用 static 变量时,我常常最终想要初始化一个变量,将另一个变量传递给它的构造函数。 也就是说,我要创建static个相互依赖的实例。
在 single.cpp 或 .h 文件中,这不是问题:实例将按照声明的顺序创建。 但是,当你想用另一个编译单元中的实例初始化一个 static 实例时,顺序似乎无法指定。 结果是,根据天气情况,可能会构建依赖于另一个实例的实例,然后才构建另一个实例。 结果是第一个实例初始化不正确。
有谁知道如何确保以正确的顺序创建 static 个对象? 我已经搜索了很长时间的解决方案,尝试了所有的解决方案(包括 Schwarz Counter 解决方案),但我开始怀疑是否有一个真正有效的解决方案。
一种可能性是 static function 成员的把戏:
Type& globalObject()
{
static Type theOneAndOnlyInstance;
return theOneAndOnlyInstance;
}
确实,这确实有效。 遗憾的是,您必须编写 globalObject().MemberFunction() 而不是 globalObject.MemberFunction(),这导致客户端代码有些混乱和不雅。
更新:感谢您的反应。 遗憾的是,看起来我确实回答了我自己的问题。 我想我必须学会忍受它……
你已经回答了你自己的问题。 Static 初始化顺序未定义,最优雅的方法(同时仍在进行 static 初始化,即不完全重构它)是将初始化包装在 function 中。
阅读从https 开始的 C++ FAQ 项目://isocpp.org/wiki/faq/ctors#static-init-order
也许你应该重新考虑是否需要那么多的全局 static 变量。 虽然它们有时很有用,但通常将它们重构为较小的本地 scope 会简单得多,尤其是当您发现某些 static 变量依赖于其他变量时。
但你是对的,没有办法确保特定的初始化顺序,所以如果你愿意,将初始化保留在 function 中,就像你提到的那样,可能是最简单的方法。
大多数编译器(链接器)实际上支持一种(不可移植的)指定顺序的方式。 例如,对于 visual studio,您可以使用init_seg pragma 将初始化安排到几个不同的组中。 AFAIK 无法保证每个组内的顺序。 由于这是不可移植的,您可能需要考虑是否可以修复您的设计以不需要它,但选项就在那里。
确实,这确实有效。 遗憾的是,您必须编写 globalObject().MemberFunction() 而不是 globalObject.MemberFunction(),这导致客户端代码有些混乱和不雅。
但最重要的是它有效,并且它是失败证明,即。 绕过正确的用法并不容易。
程序的正确性应该是您的首要任务。 另外,恕我直言,上面的 () 纯粹是风格上的——即。 完全不重要。
根据您的平台,注意过多的动态初始化。 对于动态初始值设定项,可以进行相对少量的清理(参见此处)。 您可以使用包含不同全局对象成员的全局 object 容器来解决此问题。 因此你有:
Globals & getGlobals ()
{
static Globals cache;
return cache;
}
只有一次调用 ~Globals() 才能清理程序中的所有全局对象。 为了访问全局,你仍然有类似的东西:
getGlobals().configuration.memberFunction ();
如果你真的想要,你可以将它包装在一个宏中,以使用宏节省一点点输入:
#define GLOBAL(X) getGlobals().#X
GLOBAL(object).memberFunction ();
虽然,这只是您初始解决方案的语法糖。
尽管这个线程的年龄,我想提出我找到的解决方案。 正如我之前许多人指出的那样,C++ 没有为 static 初始化排序提供任何机制。 我的建议是将每个 static 成员封装在 class 的 static 方法中,该方法依次初始化成员并以面向对象的方式提供访问权限。 举个例子,假设我们要定义名为“Math”的 class,其中包含“PI”:
class Math {
public:
static const float Pi() {
static const float s_PI = 3.14f;
return s_PI;
}
}
s_PI 将在第一次调用 Pi() 方法时初始化(在 GCC 中)。 请注意:具有 static 存储空间的本地对象具有依赖于实现的生命周期,有关详细信息,请查看2中的 6.7.4。
将 static 包装在一个方法中将解决顺序问题,但它不是线程安全的,正如其他人所指出的那样,但如果这是一个问题,您可以这样做以使其成为线程。
// File scope static pointer is thread safe and is initialized first.
static Type * theOneAndOnlyInstance = 0;
Type& globalObject()
{
if(theOneAndOnlyInstance == 0)
{
// Put mutex lock here for thread safety
theOneAndOnlyInstance = new Type();
}
return *theOneAndOnlyInstance;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.