探测器 C++ Singleton(辛格尔顿)
刚开始学习的人可能误, 误以为所有的成员变量和成员方法用于 static , 就是单例模式了:
{
public:
/* static method */
private:
static Singleton m_data; //static data member 在类中声明。在类外定义
};
Singleton Singleton::m_data;
你的类就 必须 得要有构造函数, 并确保初始化顺序).
第二, 最严重的问题, 失去了面对对象的重要特性 -- "多态", 静态成员方法不可能是 virtual 的(补充一点,静态成员方法也不可能是 const 的). Singleton类的子类没法享受 "多态" 带来的便利.
二、饿汉模式
饿汉模式 是指单例实例在程序执行时被马上执行初始化:
{
public:
static Singleton& getInstance()
{
return m_data;
}
private:
static Singleton m_data; //static data member 在类中声明。在类外定义
Singleton(){}
~Singleton(){}
};
Singleton Singleton::m_data;
这就出问题了. 由于 BSingleton m_data 静态对象可能先 ASingleton 一步调用初始化构造函数, 结果 ASingleton::getInstance() 返回的就是一个未初始化的内存区域, 程序还没跑就直接崩掉。
恩。这仅仅是理论分析的结果。以下给出一个简单的样例说明一下问题所在吧!
{
public:
static ASingleton* getInstance()
{
return &m_data;
}
void do_something()
{
cout<<"ASingleton do_something!"<<endl;
}
protected:
static ASingleton m_data; //static data member 在类中声明。在类外定义
ASingleton();
~ASingleton() {}
};
class BSingleton
{
public:
static BSingleton* getInstance()
{
return &m_data;
}
void do_something()
{
cout<<"BSingleton do_something!"<<endl;
}
protected:
static BSingleton m_data; //static data member 在类中声明,在类外定义
BSingleton();
~BSingleton() {}
};
ASingleton ASingleton::m_data;
BSingleton BSingleton::m_data;
ASingleton::ASingleton()
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton::BSingleton()
{
cout<<"BSingleton constructor!"<<endl;
}
{
;
}
BSingleton do_something!
BSingleton constructor!
BSingleton BSingleton::m_data;
这两个定义式,那么就会依次调用 ASingleton 的构造函数 和 BSingleton 的构造函数进行初始化。
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton 类中存在着其声明,那么还是能够调用到其 do_something 方法的。
ASingleton 单例对象 m_data 也就初始化完毕了。
BSingleton 的构造函数了。
//BSingleton BSingleton::m_data;
//改动成:
BSingleton BSingleton::m_data;
ASingleton ASingleton::m_data;
BSingleton constructor!
BSingleton do_something!
实现单例模式的致命缺点。
{
public:
static Singleton* getInstance()
{
if(! m_data) m_data = new Singleton();
return m_data;
}
private:
static Singleton* m_data; //static data member 在类中声明,在类外定义
Singleton(){}
~Singleton(){}
};
Singleton* Singleton::m_data = nullptr;
getInstance() 仅仅在第一次被调用时为 m_data 分配内存并初始化. 嗯, 看上去全部的问题都攻克了, 初始化顺序有保证, 多态也没问题.
例如说,有两个多线程同一时候进入到这种方法中,同一时候运行 if 语句的推断,那么就会出现两次两次初始化静态实例变量的情况。
{
// ... release resource
if (nullptr != m_data)
{
delete m_data;
m_data = nullptr;
}
}
public:
static Singleton& getInstance() {
static Singleton theSingleton;
return theSingleton;
}
/* more (non-static) functions here */
private:
Singleton(); // ctor hidden
Singleton(Singleton const&); // copy ctor hidden
Singleton& operator=(Singleton const&); //
assign op. hidden
~Singleton(); // dtor hidden
};
const BSingleton& b = BSingleton::getInstance();
static ASingleton theSingleton;
return theSingleton;
}
BSingleton& BSingleton::getInstance() {
const ASingleton & b = ASingleton::getInstance();
static BSingleton theSingleton;
return theSingleton;
}
Singleton 类, 当中 ASingleton BSingleton 的析构函数调用了CSingleton 实例的成员函数,
程序退出时, CSingleton 的析构函数 将首先被调用, 导致实例无效, 那么兴许 ASingleton BSingleton 的析构都将失败,
导致程序异常退出.
{
static bool constructed = false;
static uninitialized Singleton instance_;
if (!constructed) {
constructed = true;
new(&s) Singleton; //construct it
}
return instance_;
}
解决问题的办法是为指示类是否已经实例化的变量提供一个相互排斥锁 (尽管这样会减少效率).
{
Lock();
//锁自己实现 static
Singleton instance_;
UnLock();
return instance_;
}
五、终极方案
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
protected:
struct Object_Creator
{
Object_Creator()
{
Singleton::getInstance();
}
};
static Object_Creator _object_creator;
Singleton() {}
~Singleton() {}
};
Singleton::Object_Creator Singleton::_object_creator;
在前面的方案中:饿汉模式中,使用到了类静态成员变量,可是遇到了初始化顺序的问题; 懒汉模式中。使用到了静态局部变量,可是存在着线程安全等问题。
方法。
这样就会调用到 Singleton::getInstance()
方法初始化单例对象。那么自然 Singleton 的构造函数也就运行了。
{
public:
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
protected:
struct Object_Creator
{
Object_Creator()
{
cout<<"Object_Creator constructor"<<endl;
Singleton::getInstance();
}
};
static Object_Creator _object_creator;
Singleton() {cout<<"Singleton constructor"<<endl;}
~Singleton() {}
};
Singleton::Object_Creator Singleton::_object_creator;
Singleton constructor
{
public:
static ASingleton* getInstance()
{
static ASingleton instance;
return &instance;
}
void do_something()
{
cout<<"ASingleton do_something!"<<endl;
}
protected:
struct Object_Creator
{
Object_Creator()
{
ASingleton::getInstance();
}
};
static Object_Creator _object_creator;
ASingleton();
~ASingleton() {}
};
class BSingleton
{
public:
static BSingleton* getInstance()
{
static BSingleton instance;
return &instance;
}
void do_something()
{
cout<<"BSingleton do_something!"<<endl;
}
protected:
struct Object_Creator
{
Object_Creator()
{
BSingleton::getInstance();
}
};
static Object_Creator _object_creator;
BSingleton();
~BSingleton() {}
};
ASingleton::Object_Creator ASingleton::_object_creator;
BSingleton::Object_Creator BSingleton::_object_creator;
ASingleton::ASingleton()
{
cout<<"ASingleton constructor!"<<endl;
BSingleton::getInstance()->do_something();
}
BSingleton::BSingleton()
{
cout<<"BSingleton constructor!"<<endl;
}
BSingleton constructor!
BSingleton do_something!
class Singleton
{
struct object_creator
{
object_creator()
{
Singleton<T>::instance();
}
inline void do_nothing() const {}
};
static object_creator create_object;
public:
typedef T object_type;
static T& instance()
{
static T obj;
//这个do_nothing是确保create_object构造函数被调用
//这跟模板的编译有关
create_object.do_nothing();
return obj;
}
};
template <typename T> typename Singleton<T>::object_creator
Singleton<T>::create_object;
class QMManager
{
protected:
QMManager() {}
~QMManager() {}
friend class Singleton<QMManager>;
public:
void do_something() {};
};
int main()
{
Singleton<QMManager>::instance().do_something();
;
}
boost 通过加入一个类似 proxy-class 的方式,实现了单例模式,可是显然添加了复杂性,在实际应用中应该依据实际情况採用适当的实现方案。
探测器 C++ Singleton(辛格尔顿)的更多相关文章
- 亮点面试题&&实现Singleton(辛格尔顿)模式-JAVA版本
称号:设计一个类.我们只能产生这个类的一个实例.(来自<剑指Offer>) 解析:仅仅能生产一个实例的类是实现Singleton(单例)模式的类型.因为设计模式在面向对象程序设计中起着举足 ...
- 设计模式——辛格尔顿(Singleton)
要想正确理解设计模式,首先必须明白它是为了解决什么问题而提出来的. 设计模式学习笔记 --Shulin 转载请注明出处:http://blog.csdn.net/zhshulin 单例模式属于设计模式 ...
- Swift辛格尔顿设计模式(SINGLETON)
本文已更新为2.0语法,具体查看:一叶单例模式 一.意图 保证一个类公有一个实例.并提供一个訪问它的全局訪问点. 二.使用场景 1.使用场景 当类仅仅能有一个实例并且客户能够从一个众所周知的訪问点訪问 ...
- 【从cocos2d-x学习设计模式】第一阶段:辛格尔顿
设计模式,它总结了前辈在许多方案重用代码.它是一个想法. 因为我们爱cocos2d-x,然后我们从去cocos2d-x在设计模式中,右一起学习!本篇解释未来辛格尔顿. 提cocos2d-x中间Dire ...
- 辛格尔顿和Android
辛格尔顿(Singleton) .singleton.h,定义类的基本成员及接口 #ifndef SINGLETON_H_INCLUDE #define SINGLETON_H_INCLUDE cla ...
- 23种设计模式--单例模式-Singleton
一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
- PHP设计模式(四)单例模式(Singleton For PHP)
今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...
- The Java Enum: A Singleton Pattern [reproduced]
The singleton pattern restricts the instantiation of a class to one object. In Java, to enforce this ...
随机推荐
- Eclipse+Maven创建webapp项目<二> (转)
Eclipse+Maven创建webapp项目<二> 1.开启eclipse,右键new——>other,如下图找到maven project 2.选择maven project,显 ...
- POJ 2417 Discrete Logging 离散对数
链接:http://poj.org/problem?id=2417 题意: 思路:求离散对数,Baby Step Giant Step算法基本应用. 下面转载自:AekdyCoin [普通Baby S ...
- android-adb通用
- 栈实现java
栈是一种“先去后出”的抽象的数据结构.例如:我们在洗盘子的时候,洗完一个盘子,将其放在一摞盘子的最上面,但我们全部洗完后,要是有盘子时,我们会先从最上面的盘子开始使用,这种例子就像栈的数据结构一样,先 ...
- 玩转Web之Json(四)---json与(Object/List/Map)的相互转化
在做web应用时,经常需要将json转化成Object/list/map或者将Object/List/map转化成json,通过简单封装可以在写代码是减轻很多负担.本文将给出json转化的一系列方法. ...
- C语言中的函数指针
C语言中的函数指针 函数指针的概念: 函数指针是一个指向位于代码段的函数代码的指针. 函数指针的使用: #include<stdio.h> typedef struct (*fun_t ...
- iOS:编译错误 linker command failed with exit code 1 (use -v to see invocation)
将project不加入.m要求加入 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzI0MzQ2OQ==/font/5a6L5L2T/fontsi ...
- 做一个自动修改本机IP和mac的bat文件
原文:做一个自动修改本机IP和mac的bat文件 1.ip bat修改理论探讨 前两天我突然萌生了一个念头:能不能做一个小程序来实现自动配置或修改IP和mac,达到一键搞定的目的,这样尤其适合那些带着 ...
- IOS上传文件开发
IOS上传文件开发 在移动应用开发 文件形式上传是不可缺少的,近期把IOS这块文件上传文件代码简单的整理一下.假设大家有须要安卓这边的代码,本人也能够分享给大家! QQ群:74432915 ...
- 【干货】免费获得WebStorm软件
内容提要: 1.WebStorm简介 2.如何免费获得WebStorm 3.利用学生身份免费获得正式版WebStorm WebStorm简介 WebStorm 是一款前端开发 IDE(集成开发环境), ...