当涉及单例对象时克服静态初始化顺序失败

Overcoming static initialization order fiasco when a singleton object is involved

我在文件 x.h

中定义了一个单例 class
class x
{
 public:
     static x* x_instance;
     static x* create_x_instance
     {
        if(!x_instance)
            x_instance = new x;
        return x_instance;
     }
     void someMemberFunction()
  private:
  x() { //some code}
};

extern x *x_interface;     

在 x.cpp 我有以下内容:

x *x::x_instance = 0;
x *x_interface = x::create_x_instance();   

在y.cpp中,在另一个单例class的构造函数中,我有

x_interface->someMemberFunction();    

我遇到段错误,因为 y 在 x 之前被初始化。解决这个问题的正确方法是什么?我已经阅读了很多这方面的文章,但我仍然感到困惑。

允许编译器在首次使用时通过将其初始化为静态函数的静态成员来生成单例。

此外,您可以更进一步,以零成本为您的单例对象提供语义,同时提供可能的好处:

class x
{
    struct impl
    {
        void someMemberFunction() {

        }
    };
    static impl& get_impl() {
        static impl _{};
        return _;
    }

public:
    void someMemberFunction()
    {
        return get_impl().someMemberFunction();
    }
};

int main()
{
    auto a = x();
    a.someMemberFunction();

}

明确一点,使用静态函数的静态成员可避免初始化顺序问题:

class x
{
 public:
     static x* get_instance()
     {
         static x* theInst = new x;
         return theInst;
     }

     void someMemberFunction();
  private:
     x() { //some code}
};

后面的代码得到 x 像这样:

x* handle = x::get_instance();

以上是最小的,应该进一步改进以管理x生命周期。最好让 theImpl 是一个静态的 x 而不是指向 x 的指针,并且 get_instance() return 是一个引用而不是一个指针。

为什么需要 x_interface 作为全局或静态实例,因为您可以使用静态方法随时随地从任何地方获取 class x 的实例:create_x_instance ?

我认为在 class y 中使用它的最佳方式是:

(x::create_x_instance())->someMemberFunction();