c++中的单例工作有多精确
How precisely does a singleton work in C++
我理解你为什么要使用单例。然而,我不明白它们是如何工作的。如果这个单例对象之前已经创建过一次,并且getinstance"方法在其他地方被调用,它如何知道在内存中的单例的原始实例是什么?从阅读代码我不能理解它是从哪里来的。以下是来自Microsoft MSDN网站的简单示例。
class Singleton {
public:
static Singleton* Instance();
protected:
Singleton();
private:
static Singleton* _instance;
}
// Implementation
Singleton* Singleton::_instance = 0;
Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
我很确定它来自这一行
Singleton* Singleton::_instance = 0;
但我不知道这一行到底是做什么的,也不知道它是如何工作的。
提前感谢
真是个可怕的例子。让我们看一下细节:
static Singleton* Instance();
函数应该返回Singleton&
,而不是Singleton*
。
protected: Singleton();
protected
仅对设计为派生的类有意义。从Singleton派生并没有多大意义。往好了说,这是一个奇异的特例。单例构造函数通常是private
。
Singleton* Singleton::_instance = 0;
从c++ 11开始,nullptr
应该用于空指针。
Singleton* Singleton::Instance() { if (_instance == 0) { _instance = new Singleton; } return _instance; }
不是线程安全的。假设有3个线程(A, B和C)同时调用Instance()
。这三个节点第一次同时到达if (_instance == 0)
。因此,条件对它们都为真,所以它们都进入if
块-导致三个实例被创建!
我很确定它来自这一行
Singleton* Singleton::_instance = 0;
但我不知道这一行到底是做什么的,也不知道它是如何工作的。
初始化Singleton
类的static
_instance
成员变量。在此上下文中,static
意味着变量独立于任何Singleton
实例存在,因此您可以在static
成员函数中访问它,如Instance()
。
从c++ 11开始,实现单例的线程安全方法是使用static
局部变量:
Singleton& Singleton::Instance() {
static Singleton instance;
return instance;
}
该技术已经存在了很长时间,但直到c++ 11之后才成为线程安全的,因为只有c++ 11标准正式承认多线程的存在,包括对局部static
变量的某些保证。
这种技术的缺点是,如果你有多个单例类,并且一个单例类的析构函数访问另一个单例类,你可能会遇到销毁顺序问题。
有解决这个问题的方法,但我不会在这里深入讨论,因为现在你已经学习了一些关于Singleton的事情- 不要使用模式
现在大多数程序员都经历了惨痛的教训,singleton只是伪装的全局变量,应该尽量少用。它们在你的代码中创建了全局依赖,使得测试和模块化变得更加困难或不可能,和很难正确和安全地实现。Singleton是《四人帮》里的头号败类。
顺便说一下,看看微软自己在你引用的页面顶部是怎么说的:
此内容已过时,不再维护。它是提供给仍在使用这些服务的个人是一种礼貌技术。
如果单例已经创建了一次之前和"get实例"方法已被调用在其他地方,它如何知道在内存中的单例的原始实例是什么?
静态数据通常存储在可执行文件的。data部分。
当你的代码使用静态数据时,它将被翻译成从数据段引用一些绝对地址的汇编指令,例如
A1 00 F0 22 01 mov eax,dword ptr ds:[0122F000h]
你的代码被编译和链接,假设你的程序将被加载到某个预期的基址。但情况并非总是如此,因此你的可执行文件还包含重定位部分,其中包含有关文件中这些绝对地址的偏移量信息。
当你的程序被加载到内存中时,操作系统会注意将这些绝对地址替换为实际地址。
下面是一个不那么令人困惑的例子。让我们只保留Singleton作为设计模式的名称,而不使用它作为类的名称。
Logger* Logger::m_pInstance = NULL;
/* Use this to get the instance of Logger instead of "new" */
Logger* Logger::Instance()
{
if (!m_pInstance) { // Only allow one instance of class to be generated.
m_pInstance = new Logger;
}
return m_pInstance;
}
/* some other method in the logger class */
bool Logger::openLogFile(std::string _logFile)
{
...
...
...
}
基本上,如果你想要这个类的一个实例,你调用instance()方法。它将始终返回完全相同的对象给你。
是的,有些人因为这样或那样的原因不喜欢Singleton…不知道为什么。所有的模式都有自己的位置和用途。
学习尽可能多的设计模式以及何时使用它们,总比不知道它们要好。https://en.wikipedia.org/wiki/Software_design_pattern 单例模式有时非常有用。
这句话的意思是:
Singleton* Singleton::Instance() {
if (_instance == 0) {
_instance = new Singleton;
}
return _instance;
}
已经创建了这个对象(在这个例子中是Singleton类型),如果是,返回它。如果没有,创建新的"Singleton"对象并返回。
换句话说,无论你调用Instance()方法多少次,它总是返回相同的对象给你。
- 为什么在单例中,检查类==空?
- C++ 实现模板单例类时出现链接错误
- 在类中存储单例的指针
- C++中的单例实现在调用 getInstance 函数时不会产生相同的类实例
- 具有非默认构造函数的单例类
- 使用 std::call_once 实现类似单例的功能
- 为什么单例使用指针而不是引用?
- 提升单例池release_memory vs purge_memory
- 具有 QObject 继承的单例 - Qt
- 单例类析构函数无法清理 (SDL_Quit) MinGW
- C++单例,不会为此文档加载任何符号
- 使用 CRTP 实现单例
- C++单例模板类使我的程序崩溃
- Linux 中共享库中的单例无法按预期工作
- 为什么单例在这里工作,尽管静态变量被重新初始化为 NULL
- 为什么这个单例类代码工作正常
- 单例示例如何工作
- c++单例,stackoverflows的例子不工作
- c++中的单例工作有多精确
- 两个线程访问单例类 - 无法正常工作