单例模式的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.单例类必须自己创建 ...
随机推荐
- html的<a>标签,表单,内嵌框架
一. <a>标签 0. 用图片当链接,就是把图片当成链接文字即可 <a href="http://www.baidu.com/" title="跳 ...
- Objective-C语法基础:面向对象编程特点的总结
1.类的声明与实现 Objective-C类的声明要写在@interface 与 @end之间,实现要写在@implementation 与 @end之间 2.类的-方法和+方法 类的-方法即类的实例 ...
- P3952 时间复杂度
P3952 时间复杂度 题目描述 小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机 ...
- 【BZOJ1296】[SCOI2009]粉刷匠 (DP+背包)
[SCOI2009]粉刷匠 题目描述 \(windy\)有 \(N\) 条木板需要被粉刷. 每条木板被分为 \(M\) 个格子. 每个格子要被刷成红色或蓝色. \(windy\)每次粉刷,只能选择一条 ...
- 动手玩转Docker(一)
在学习docker之前,先了解一下什么是docker,以及docker技术存在的意义. Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上 ...
- JavaWeb学习笔记(十九)—— 分页
一.MySQL中的分页 格式:select * from 表 limit ?,?; 参数1:开始索引start,默认值:.必须是正数 参数2:每页显示个数 pageSize 例如: ,; #第一页,每 ...
- JAVA编译结果中有****$1.class的
java编译后的文件名字带有$接数字的就是匿名内部类的编译结果,接名字的就是内部类的编译结果 例如:TestFrame$1.class是匿名内部类的编译结果,TestFrame$MyJob.class ...
- Pycharm与github的秘密
GIT介绍 GIT文章请看老男孩教育-银角大王的博客: http://www.cnblogs.com/wupeiqi/articles/7295372.html Git 是一个开源的分布式版本控制软件 ...
- hadoop job -kill 和 yarn application -kill 区别
hadoop job -kill 调用的是CLI.java里面的job.killJob(); 这里会分几种情况,如果是能查询到状态是RUNNING的话,是直接向AppMaster发送kill请求的.Y ...
- 使用 Dotfuscator 对代码进行混淆
Dotfuscator 简介 作为一种高级语言,c# 类库很容易被 .NET Reflector 这样的工具反编译.攻击者很容易从代码中找到数据库连接方式,加解密方法等重要信息.使用 dnspy 这样 ...