求解初始化顺序:
首先,这只是一个临时的解决方法,因为您有一些想要删除的全局变量,但还没有时间(您最终会删除它们,不是吗?:-)
class A
{
public:
// Get the global instance abc
static A& getInstance_abc() // return a reference
{
static A instance_abc;
return instance_abc;
}
};
这将保证它在首次使用时初始化并在应用程序终止时销毁。
多线程问题:
C++11 does保证这是线程安全的:
§6.7 [stmt.dcl] p4
如果在初始化变量时控制同时进入声明,则并发执行应等待初始化完成。
然而,C++03 确实not官方保证静态函数对象的构造是线程安全的。所以从技术上来说getInstance_XXX()
方法必须用临界区来保护。好的一面是,gcc 有一个显式补丁作为编译器的一部分,保证每个静态函数对象即使在存在线程的情况下也只会被初始化一次。
请注意:Do not使用双重检查锁定模式 https://en.wikipedia.org/wiki/Double-checked_locking尝试避免锁定的成本。这在 C++03 中不起作用。
创作问题:
在创建时,没有任何问题,因为我们保证它是在创建之后才可以使用的。
破坏问题:
在对象被销毁后访问该对象存在潜在的问题。仅当您从另一个全局变量的析构函数访问该对象时才会发生这种情况(通过全局,我指的是任何非局部静态变量)。
解决方案是确保你强制执行破坏命令。
请记住,破坏的顺序与构造的顺序完全相反。因此,如果您在析构函数中访问该对象,则必须保证该对象没有被销毁。为此,您必须保证在构造调用对象之前完全构造对象。
class B
{
public:
static B& getInstance_Bglob;
{
static B instance_Bglob;
return instance_Bglob;;
}
~B()
{
A::getInstance_abc().doSomthing();
// The object abc is accessed from the destructor.
// Potential problem.
// You must guarantee that abc is destroyed after this object.
// To guarantee this you must make sure it is constructed first.
// To do this just access the object from the constructor.
}
B()
{
A::getInstance_abc();
// abc is now fully constructed.
// This means it was constructed before this object.
// This means it will be destroyed after this object.
// This means it is safe to use from the destructor.
}
};