单例 - 实施。使用静态 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
问题
- 我们能否同时考虑这两个 impl。作为一个有效的暗示。设计模式?
- 两者在功能上是否相同?
动机
背景
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
对象可以在运行时系统初始化 之前尝试访问静态成员 。
所以对于你的问题:
- Can we consider both impl. as a valid impl. of the design pattern?
- Are both, functionally, the same?
没有。使用 static
成员是危险的,因为如果 nullptr
初始化在调用之前没有发生,那么 SingletonCSM::GetInstance()
的调用者可以访问非创建的对象。 static
函数方法是推荐的方法,因为它保证每个调用者都已完成初始化。
I just don't understand what was the problem and why was it solved?
在你的情况下,转向更危险的方法似乎已经阻止了你的崩溃。我无法解释为什么会这样。但是您可能没有解决问题,可能是您在其他地方有未定义的行为,在这种情况下只是停止表现,但稍后可能会通过不同的更改重新出现。
给大家带来两种不同的单例设计模式植入:
静态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
问题
- 我们能否同时考虑这两个 impl。作为一个有效的暗示。设计模式?
- 两者在功能上是否相同?
动机
背景
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
对象可以在运行时系统初始化 之前尝试访问静态成员 。
所以对于你的问题:
- Can we consider both impl. as a valid impl. of the design pattern?
- Are both, functionally, the same?
没有。使用 static
成员是危险的,因为如果 nullptr
初始化在调用之前没有发生,那么 SingletonCSM::GetInstance()
的调用者可以访问非创建的对象。 static
函数方法是推荐的方法,因为它保证每个调用者都已完成初始化。
I just don't understand what was the problem and why was it solved?
在你的情况下,转向更危险的方法似乎已经阻止了你的崩溃。我无法解释为什么会这样。但是您可能没有解决问题,可能是您在其他地方有未定义的行为,在这种情况下只是停止表现,但稍后可能会通过不同的更改重新出现。