Singleton - Impl。使用静态类成员与静态成员变量

时间:2016-09-21 12:39:52

标签: c++ dll singleton in-memory make-shared

为您带来两种不同的单例设计模式:

静态类成员

class SingletonCSM;
using SingletonCSMSp = std::shared_ptr < SingletonCSM > ;

class SingletonCSM
{
public:

    ~SingletonCSM()  { spInstance = nullptr; }

    static SingletonCSMSp GetInstance()
    {
        if (!spInstance)
            spInstance = std::make_shared<SingletonCSM>();

        return spInstance;
    }

private:

    SingletonCSM() {}

    // will be intilized in the cpp: SingletonCSMSp SingletonCSM::spInstance = nullptr;
    static SingletonCSMSp spInstance; 
};

静态成员变量

class SingletonFSV;
using SingletonFSVSp = std::shared_ptr < SingletonFSV > ;

class SingletonFSV
{
public:

    ~SingletonFSV() {}

    static SingletonFSVSp GetInstance()
    {
        static SingletonFSVSp spInstance = std::make_shared<SingletonFSV>();
        return spInstance;
    }

private:

    SingletonFSV() {}

};

我总是使用第一个impl。 SingletonCSM。在我们的代码中,我遇到了一个impl。比如SingletonFSV

问题

  1. 我们可以同时考虑impl。作为一个有效的impl。设计模式?
  2. 两者在功能上是否相同?
  3. 动机

    背景

    SingletonFSV是作为DLL项目的一部分实现的。这个在VS 2013中编译的DLL由exe文件加载到内存中并运行。

    问题

    我将VS升级为VS 2015,编译DLL项目并运行exe。它突然崩溃了。在调试时,我注意到崩溃发生在DLL本身。被make_shared调用的GetInstance()返回nullptr并自然导致分段错误。

    解决方案

    我已经改变了SingletonFSV impl。到SingletonCSM并且崩溃停止了。 make_shared返回了一个有效的指针,问题就解决了。

    问题

    我只是不明白这是什么问题,为什么会解决?

1 个答案:

答案 0 :(得分:1)

当你在一个函数中放置一个static变量时,它会在第一次调用该函数时被创建,因此可以保证它已被实例化为该函数的所有调用者。

声明static的成员可以在调用函数之前或之后实例化,因为转换单元之间的初始化顺序未定义。因此,全局对象或static对象可以在运行时系统初始化之前尝试访问静态成员

那么你的问题:

  
      
  1. 我们可以同时考虑impl。作为一个有效的impl。设计模式?
  2.   
  3. 两者在功能上是否相同?
  4.   

没有。使用static成员是危险的,因为SingletonCSM::GetInstance()的调用者可以在调用之前未进行nullptr初始化时访问未创建的对象。 static函数方法是推荐的方法,因为它保证每个调用者的初始化都已完成。

  

我只是不明白问题是什么,为什么会解决?

在你的情况下,转向更危险的方法似乎已经停止了你的崩溃。我无法解释为什么会这样。但是你可能没有删除这个问题,可能是你在其他地方有未定义的行为,在这种情况下只是停止了显示但是后来可能会有不同的变化重新出现。