单例模式的c++实现
#pragma once #include <iostream>
#include <memory>
#include <Windows.h>
using namespace std;
/*************************************************************************************** 1、首先要有一个创建实例的静态函数GetInstance
2、实现的方式既可以通过new动态创建,也可以通过static静态局部变量实现
3、创建的时机既可以通过静态变量初始化时创建,也可以在调用GetInstance函数时再创建,通过静态变量的初始化的好处是
它是在进入主函数之前创建成功的可以避免多线程的问题,但是坏处就是在程序启动时初始化会拖慢启动过程。
4、为了防止通过调用构造函数创建实例,要将类的构造、复制构造和赋值构造函数设为私有的
5、GetInstance函数的返回值既可以是指针,又可以是引用,当是指针的时候要防止它在中途被delete掉,因此要将析构函数设为私有的
6、这种模式有点像全局变量,但还是有区别的,单件的作用是保证只有一份实例,而能够全局访问是它附带的功能。 ********************************************************//////////////////////////////////////
class singleton1
{
public:
static singleton1* GetInstance()
{
if(ptr == NULL)
ptr = new singleton1;
return ptr;
} static void show()
{
cout << "singleton1::show" << endl;
} private:
~singleton1()
{
cout << "dest singleton1" << endl;
}
static singleton1* ptr;
singleton1()
{
cout << "cstr singleton1" << endl;
} singleton1(const singleton1 &);
singleton1& operator=(const singleton1 &);
}; singleton1* singleton1::ptr = new singleton1; /*****************
1、在上面的实现中,使用指针时,不能销毁实例,只有当程序结束时才由系统回收,考虑将指针设计成智能指针shared_ptr,
但是智能指针的回收还是要调用析构函数,声明为public,指针随时会被delete,有很多问题,所以这种方法是不太实用
*****************/
class singleton3
{
public:
~singleton3()
{
cout << "dest singleton3" << endl;
} static singleton3* GetInstance()
{
if(ptr.get() == NULL)
ptr.reset(new singleton3);
return ptr.get();
} static void show()
{
cout << "singleton3::show" << endl;
} private:
static shared_ptr<singleton3> ptr;
singleton3(){}
singleton3(const singleton3 &);
singleton3& operator=(const singleton3 &);
}; shared_ptr<singleton3> singleton3::ptr; /****************************************
1、上面的实现都是基于new动态创建,并且返回的都是指针类型,这个实现基于静态局部变量,并且返回引用类型
2、返回引用而不是指针的好处是,不用担心中间会被delete掉
3、采用静态局部变量的好处是,内存管理交给系统,不需要手动管理
****************************************/
class singleton4
{
public:
~singleton4()
{
cout << "dest singleton4" << endl;
} static singleton4& GetInstance()
{
static singleton4 s;
return s;
} static void show()
{
cout << "singleton4::show" << endl;
} private:
singleton4(){;}
singleton4(const singleton4 &);
singleton4& operator=(const singleton4 &);
}; /***************************
1、如果是在GetInstance函数中创建实例,并且是多线程的话,如果有多个线程同时调用该函数,
则可能会创建多个实例,所以要对创建过程进行加锁处理
**************************/
CRITICAL_SECTION g_cs;
class Lock
{
public:
Lock()
{
InitializeCriticalSection(&g_cs);
} void LockOn()
{
EnterCriticalSection(&g_cs);
} void LockOff()
{
LeaveCriticalSection(&g_cs);
} ~Lock()
{
DeleteCriticalSection(&g_cs);
}
};
Lock g_lock; class singleton5
{
public:
~singleton5()
{
cout << "dest singleton5" << endl;
} static singleton5* GetInstance()
{
if(ptr == NULL)
{
//采用双重判断是为了提高效率,防止每次都要执行加锁过程
g_lock.LockOn();
if(ptr == NULL)
ptr = new singleton5;
g_lock.LockOff();
} return ptr;
} static void show()
{
cout << "singleton5::show" << endl;
} private:
static singleton5* ptr;
singleton5(){}
singleton5(const singleton5 &);
singleton5& operator=(const singleton5 &);
};
singleton5* singleton5::ptr = NULL; /******************
1、上面的实现虽然满足了多线程调用,但是实际中可能会有很多类都要设计成实例模式,
那么就需要都按照上面那样实现一遍,不能重用,下面的模板类就可以满足重用的需求
*******************************/
template <typename T>
class Singleton
{
public:
static T& Instance()
{
if (m_pInstance == NULL)
{
//Lock lock;
g_lock.LockOn();
if (m_pInstance == NULL)
{
m_pInstance = new T;
atexit(&Destroy);//将Destroy注册为程序结束时的执行函数释放内存
} //return *m_pInstance;
g_lock.LockOff();
} return *m_pInstance;
} protected:
Singleton(void)
{
cout << "cstr Singleton" << endl;
}
virtual ~Singleton(void)
{
cout << "dest Singleton" << endl;
} private:
Singleton(const Singleton& rhs)
{
cout << "copy cstr Singleton" << endl;
}
Singleton& operator = (const Singleton& rhs)
{
cout << "= cstr Singleton" << endl;
} static void Destroy()
{
if (m_pInstance != NULL)
delete m_pInstance;
m_pInstance = NULL;
} static T* m_pInstance;
}; template <typename T>
T* Singleton<T>::m_pInstance = NULL; //实际的单例类就按照下面的方式实现
class SingletonInstance : public Singleton<SingletonInstance>
{
public:
friend Singleton<SingletonInstance>;
void show()
{
cout << "SingletonInstance::show" << endl;
}
//
private:
SingletonInstance()
{
cout << "cstr SingletonInstance" << endl;
}
virtual ~SingletonInstance(void)
{
cout << "dest SingletonInstance" << endl;
} SingletonInstance(const SingletonInstance& rhs)
{
cout << "copy cstr SingletonInstance" << endl;
}
}; //测试类
class SingletonTest
{
public:
SingletonTest()
{
//singleton1& s1 = singleton1::GetInstance1();
//s1.show(); //singleton1 *p1 = singleton1::GetInstance();
//p1->show();
////delete p1; //singleton3 *p3 = singleton3::GetInstance();
//p3->show(); //singleton4 &p4 = singleton4::GetInstance();
//p4.show(); //singleton5 *p5 = singleton5::GetInstance();
//p5->show(); SingletonInstance &si = SingletonInstance::Instance();
si.show();
}
};
单例模式的c++实现的更多相关文章
- C++实现线程安全的单例模式
在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...
- 23种设计模式--单例模式-Singleton
一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...
- angular2系列教程(十)两种启动方法、两个路由服务、引用类型和单例模式的妙用
今天我们要讲的是ng2的路由系统. 例子
- java设计模式之--单例模式
前言:最近看完<java多线程编程核心技术>一书后,对第六章的单例模式和多线程这章颇有兴趣,我知道我看完书还是记不住多少的,写篇博客记录自己所学的只是还是很有必要的,学习贵在坚持. 单例模 ...
- 设计模式C#合集--单例模式
单例模式 代码: 第一种: private static Singleton singleton = null; private Singleton() { } public static Singl ...
- 设计模式之单例模式(Singleton)
设计模式之单例模式(Singleton) 设计模式是前辈的一些经验总结之后的精髓,学习设计模式可以针对不同的问题给出更加优雅的解答 单例模式可分为俩种:懒汉模式和饿汉模式.俩种模式分别有不同的优势和缺 ...
- GOF23设计模式之单例模式
·核心作用: -保证一个类只有一个实例,并且提供一个访问该实例的全局访问点. ·常见应用场景: -Windows的Task Manager(任务管理器)就是很典型的单例模式 -Windows的Recy ...
- GJM : C#设计模式(1)——单例模式
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- PHP设计模式(四)单例模式(Singleton For PHP)
今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...
- java设计模式之单例模式(几种写法及比较)
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
随机推荐
- freemarker模板跟java代码放在一起
在配置 freemarkerConfig时加上 <property name="templateLoaderPath" value="classpath:hello ...
- 简单的数字校验JS
/** *张衍涛 * 数字校验 v:校验的元素 l:要保留的小数点位数 */ function checkNumber(v,l){ var val=v.value; if(isNaN(val) || ...
- js,timeout,promise执行顺序
总结 macro-task包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering. micro-task包括 ...
- HTML DOM--基础概述
DOM: Document Object Model(文档对象模型)的简写,那么,这是一种什么样的模型,简单点来说,就是将文档当成了一棵树.它独立于平台与语言,允许程序与脚本动态地访问.更新文档的结构 ...
- nginx克隆之后问题
[alert] kill(2942, 1) failed (No such process) 背景:虚拟机克隆之后启动service nginx reload报这个错,而且没有日志 根据这个博文htt ...
- 趣味测试类微信小程序
先说说项目需求吧, l 点击[再测一次],重新开始测试流程,主持人回复第一个题目,流程同上:答完全部题目后,底部不显示[立即开始分析]按钮,而是直接展示结果,且上一次测试内容不清空:如退出再进来,则 ...
- spider_keeper
一 简介 spider_keeper 是一款开源的spider管理工具,可以方便的进行爬虫的启动,暂停,定时,同时可以查看分布式情况下所有爬虫日志,查看爬虫执行情况等功能. 二 安装 部署 安装环境 ...
- 基础篇:6.2)形位公差-符号 Symbol
本章目的:了解定义形位公差的符号. 1.公差特征项目的符号(GM新标准) //形位公差共:5类14个,4,2,3,3,2. 2.附加符号(GM新标准) //①基本尺寸(理论尺寸)没有公差,无需检验(不 ...
- ONTAK2010 Peaks加强版(离线&在线)
题面 弱化版:luogu 强制在线版:bzoj 题解 本题有两种解法 离线算法:线段树合并 先看一道简单题[USACO18JAN]MooTube 本题就是在此基础上求第\(k\)高的点 首先把询问和路 ...
- 233 Matrix(矩阵快速幂+思维)
In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233 ...