单例 - 实施。使用静态 class 成员与静态成员变量

Singleton - Impl. using static class member vs. static member variable

给大家带来两种不同的单例设计模式植入:

静态class成员

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。作为一个有效的暗示。设计模式?
  2. 两者在功能上是否相同?

动机

背景

Class SingletonFSV 作为 DLL 项目的一部分实现。此 DLL 在 VS 2013 中编译,由 exe 文件和 运行.

加载到内存中

问题

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

解决方案

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

问题

我只是不明白问题出在哪里,为什么解决了?

当您将 static 变量放入函数中时,它会在第一次调用该函数时创建,因此可以保证它已实例化给 所有 调用者函数。

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

所以对于你的问题:

  1. Can we consider both impl. as a valid impl. of the design pattern?
  2. Are both, functionally, the same?

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

I just don't understand what was the problem and why was it solved?

在你的情况下,转向更危险的方法似乎已经阻止了你的崩溃。我无法解释为什么会这样。但是您可能没有解决问题,可能是您在其他地方有未定义的行为,在这种情况下只是停止表现,但稍后可能会通过不同的更改重新出现。