实际上,通过使用单例,您可以在 C++ 中非常有效地控制全局/静态对象的初始化顺序。
例如,假设您有:
class Abc
{
public:
void foo();
};
以及在全局范围内定义的相应对象:
Abc abc;
然后你有一个类:
class Def
{
public:
Def()
{
abc.foo();
}
};
它还有一个在全局范围内定义的对象:
Def def;
在这种情况下,您无法控制初始化顺序,如果首先初始化 def,那么您的程序很可能会崩溃,因为它正在调用尚未初始化的 Abc 上的 foo() 方法。
解决方案是让全局范围内的函数执行如下操作:
Abc& abc()
{
static Abc a;
return a;
}
然后 Def 看起来像:
class Def
{
public:
Def()
{
abc().foo();
}
};
这样, abc 始终保证在使用之前被初始化,因为这将在第一次调用 abc() 函数期间发生。同样,您应该对 Def 全局对象执行相同的操作,以使其也不会有任何意外的初始化依赖项。
Def& def()
{
static Def d;
return d;
}
如果除了简单地确保在使用之前初始化所有内容之外,还需要严格控制初始化顺序,请将所有全局对象放入 Global 单例中,如下所示。
struct Global
{
Abc abc;
Def def;
};
Global& global()
{
static Global g;
return g;
}
并参考这些项目如下:
//..some code
global().abc.foo();
//..more code here
global().def.bar();
无论哪一个首先被调用,C++ 成员初始化规则都将保证 abc 和 def 对象按照它们在 Global 类中定义的顺序进行初始化。