实现单例模式C++版本
还是先看最简单的C++单例模式
class CSingleton
{
private:
CSingleton(){}
static CSingleton *pInstance; public:
static CSingleton* getInstance()
{
if(pInstance == NULL)
{
pInstance = new CSingleton();
}
return pInstance;
}
};
大多数时候,这样的实现都不会出现问题。有经验的读者可能会问,m_pInstance指向的空间什么时候释放呢?更严重的问题是,该实例的析构函数什么时候执行?
如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面的代码无法实现这个要求。我们需要一种方法,正常的删除该实例。
可以在程序结束时调用GetInstance(),并对返回的指针掉用delete操作。这样做可以实现功能,但不仅很丑陋,而且容易出错。因为这样的附加代码很容易被忘记,而且也很难保证在delete之后,没有代码再调用GetInstance函数。
一个妥善的方法是让这个类自己知道在合适的时候把自己删除,或者说把删除自己的操作挂在操作系统中的某个合适的点上,使其在恰当的时候被自动执行。
我们知道,程序在结束的时候,系统会自动析构所有的全局变量。事实上,系统也会析构所有的类的静态成员变量,就像这些静态成员也是全局变量一样。利用这个特征,我们可以在单例类中定义一个这样的静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。
class CSingleton
{
private:
CSingleton(){}
static CSingleton *pInstance; class CGarbo//它的唯一工作就是在析构函数中删除CSingleton的实例
{
public:
~CGarbo()
{
if(pInstance)
{
delete pInstance;
}
}
};
static CGarbo garbo;//定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数 public:
static CSingleton* getInstance()
{
if(pInstance == NULL)//判断是否第一次调用
{
pInstance = new CSingleton()
} return pInstance;
}
};
类CGarbo被定义为CSingleton的私有内嵌类,以防该类被在其他地方滥用。
程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。
使用这种方法释放单例对象有以下特征:
在单例类内部定义专有的嵌套类;
在单例类内定义私有的专门用于释放的静态成员;
利用程序在结束时析构全局变量的特性,选择最终的释放时机;
使用单例的代码不需要任何操作,不必关心对象的释放。
使用局部静态变量,非常强大的方法,完全实现了单例的特性,而且代码量更少,也不用担心单例销毁的问题。
但使用此种方法也会出现问题,当如下方法使用单例时问题来了,
Singleton singleton = Singleton :: GetInstance();
这么做就出现了一个类拷贝的问题,这就违背了单例的特性。产生这个问题原因在于:编译器会为类生成一个默认的构造函数,来支持类的拷贝。
最后没有办法,我们要禁止类拷贝和类赋值,禁止程序员用这种方式来使用单例。
class CSingleton
{
private:
CSingleton() //构造函数是私有的
{
}
CSingleton(const CSingleton &);
CSingleton & operator = (const CSingleton &);
public:
static CSingleton & GetInstance()
{
static CSingleton instance; //局部静态变量
return instance;
}
};
这时的拷贝构造函数和赋值拷贝构造函数需要声明成私有的,并且只声明不实现。这样,如果在外部通过构造函数、拷贝构造函数、赋值拷贝构造函数等新建实例都会产生编译器错误。如果类的成员函数或者友元函数创建实例会引起连接器的错误。
到这里还是单线程的模式,如果想在多线程下运行,还必须想上一篇C#版本的单例模式一样,利用同步锁。
Singleton* Singleton::Instantialize()
{
if(pInstance == NULL)
{ //double check
Lock lock(cs); //用lock实现线程安全,用资源管理类,实现异常安全
//使用资源管理类,在抛出异常的时候,资源管理类对象会被析构,析构总是发生的无论是因为异常抛出还是语句块结束。
if(pInstance == NULL)
{
pInstance = new Singleton();
}
}
return pInstance;
}
实现单例模式C++版本的更多相关文章
- C# 单例模式Lazy<T>实现版本
非Lazy版本的普通单例实现: public sealed class SingletonClass : ISingleton { private SingletonClass () { // the ...
- 单例模式简介以及C++版本的实现
本篇博文主要内容参考 C++的单例模式一文,在此,为原作者耐心细致的分析讲解,表示感谢.本文将结合此篇文章,给出自己做实验后的理解以及代码,作为今天学习的小结. 单例模式,它的意图是保 ...
- 06002001单例模式C#实现版本
书名:设计模式之禅 作者:秦小波 出版社:机械工业出版社 1 描述 确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例 2 UML类图 图1-1 单例模式类图 3 代码 Singleto ...
- Javascript单例模式概念与实例
前言 和其他编程语言一样,Javascript同样拥有着很多种设计模式,比如单例模式.代理模式.观察者模式等,熟练运用Javascript的设计模式可以使我们的代码逻辑更加清晰,并且更加易于维护和重构 ...
- C#初学单例模式
版本1:最简单的单例模式 public class MySingleton { private MySingleton() //构造函数,注意private { } private static My ...
- 【白话设计模式四】单例模式(Singleton)
转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...
- Java序列化、反序列化和单例模式
学习JAVA的时候,特别是涉及到网络编程时,我们时常让我们的实体类实现一个接口 public class Entity implements Serializable{ } 这样子我们可以通过输入输出 ...
- 《JS设计模式笔记》 1,单例模式
<script type="text/javascript"> //单例模式 //1,每次点击都会生成一个新的div var createMask=function ( ...
- C# 中实现单例模式
文章目录 简介 不安全线程的单例模式 简单安全线程带锁 双重检查 - 带锁 安全初始化 安全并且懒汉式静态初始化 带泛型的懒汉式单例 异常 提高效率 总结 简介 单例模式是软件工程中广为人知的设计模式 ...
随机推荐
- 确定比赛名次(map+邻接表 邻接表 拓扑结构 队列+邻接表)
确定比赛名次 Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- 循环对XML文档添加Attribute以及移除Element 【转】
如下面的图片要求,需要把左边的xml文改为右边的文档. 需要添加Attribute,移除Element,但是所添加的Attribute值已经跟被移除的Element值不相同.实现方法可以参考<对 ...
- Objective-C 内存管理之 _ARC
内存管理之 ARC 和 自己主动释放池 一.ARC 中的变量全部权修饰符 变量修饰符,主要用来标识对象的生命周期.在手动内存管理方式中没有这些概念. ARC 环境下变量全部权修饰符主要有以下几个: _ ...
- 实现Android语音识别服务接口 RecognitionService的方法
之前的一篇文章介绍过SpeechRecognizer类,该类能够作为对外的一个接口,并通过Intent传递一个ComponentName获取可支持语音识别的功能的服务,一般的用户手机中假设安装了语音识 ...
- css3前端工具
随着CSS3的出现,CSS3讨论的话题越来越多了,现在各种教程也是多如牛毛,不比一年前的时候,找个资料要捞遍整个互联网,而且还很难找到自己需要的参考资料.从侧面也说明,CSS3对于前端工程师来说,越来 ...
- 学习Java这几个快捷键你得知道(不断更新中)
java中的System.out.println();的快捷键 --------先输入sysout 在按 alt + /
- OCP-1Z0-053-V12.02-512题 【转】
http://blog.csdn.net/gisinfo/article/details/8159875 1.Which two statements correctly describe the r ...
- 又一个类dapper轮子:VIC.DataAccess
DataAccess Author: Victor.X.Qu Email: fs7744@hotmail.com DataAccess is a c# project for sql data map ...
- JavaSE复习日记 : 循环终止语句(break/break outerFor/continue)
最近没网,但攒了几天的博客,这次逮到机会发博客,直接三篇走起; /* * 循环终止语句: break/ break outerFor/ continue */ /* * break语句 * 1. 用于 ...
- JavaWeb核心编程之(三.5)HTTP请求和接受表单数据
HTTP简介WEB浏览器与WEB拂去其之间的一问一答的交互过程, 必须遵循一定的规则,这个规则就是HTTP协议HTTP是hypertext transfer protocol(超文本传输协议)的简写, ...