【问题标题】:Singleton - Impl. using static class member vs. static member variable单例 - 实施。使用静态类成员与静态成员变量
【发布时间】:2016-09-21 12:39:51
【问题描述】:

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

静态类成员

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. 两者在功能上是否相同?

动机

背景

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

问题

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

解决方案

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

问题

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

【问题讨论】:

  • 你不应该内联static SingletonFSVSp GetInstance()
  • 请注意,这些都不是单例。它们都有公共构造函数,这意味着您可以创建任意数量的实例。
  • @DieterLücking 与问题有关还是只是一般性评论? 10 倍。
  • @NathanOliver 正确,我会更新问题
  • @idanshmu ...该内联函数的静态变量(未放入特定的翻译单元)是问题。

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


【解决方案1】:

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

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

所以对于你的问题:

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

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

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

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

【讨论】:

  • 好的。但它如何解释问题?我希望SingletonFSV 始终工作,而SingletonCSM 可能偶尔会崩溃。但问题恰恰相反
  • @idanshmu 是的,我无法回答您的第三个问题。我误读了您的问题,并假设函数静态方法解决了它。这听起来像是调试器的工作,因为原则上,使用静态成员是有问题的,应该避免,而使用静态函数被认为是安全的选择。
猜你喜欢
  • 2015-08-23
  • 1970-01-01
  • 2016-05-20
  • 1970-01-01
  • 1970-01-01
  • 2012-04-13
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多