单例模式的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.单例类必须自己创建 ...
随机推荐
- 不用split调转字符串
- 关于OC中的block自己的一些理解(二)
一.block延伸:页面间反向传值 1)first页面的代码 - (void)viewDidLoad { [super viewDidLoad]; [self setupBtn]; self.view ...
- Centos7 安装node(8版本)
最简洁的命令 yum -y update yum -y install gcc make gcc-c++ openssl-devel wget vim(后面两个如果没有再选择安装) cd /usr/l ...
- Oracle分析函数、窗口函数简单记录汇总
一.分析函数.窗口函数一般形式 1.分析函数的形式分析函数带有一个开窗函数over(),包含三个分析子句:分组(partition by), 排序(order by), 窗口(rows) ,他们的使用 ...
- Zookeeper---系统学习
1.概述 1.1 Zookeeper解决了什么问题? 分布式环境中 协调和管理服务 是一个复杂的过程: Zookeeper通过 其简单的架构和API 解决了这个问题,Zookeeper ...
- vue笔记精华部分
以 _ 或 $ 开头的属性 不会 被 Vue 实例代理,因为它们可能和 Vue 内置的属性.API 方法冲突.你可以使用例如 vm.$data._property 的方式访问这些属性. mixin的使 ...
- Ubuntu下配置安装Hadoop 2.2
---恢复内容开始--- 这两天玩Hadoop,之前在我的Mac上配置了好长时间都没成功的Hadoop环境,今天想在win7 虚拟机下的Ubuntu12.04 64位机下配置, 然后再建一个组群看一看 ...
- less变量插值
在使用less的过程中,我在background的中引用图片路径,希望先确定一个baseurl,然后再在url中使用拼接字符串的方式拼接,尝试多次,失败. 实际上less的变量插值是有自己的一套规则的 ...
- java项目部署总结
环境问题一定要搞定,今天下午因为我本机的mysql版本较高,部署一个java项目,mysql jar驱动包8.0的版本无法使用,浪费了好长时间找问题. 总结:遇到问题多方位思考,尽快解决掉,提高工作效 ...
- 日调度万亿次,微服务框架TSF大规模应用——云+未来峰会开发者专场回顾
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 演讲者:张浩 腾讯云中间件产品负责人 背景:众多开发者中,一定经历类似的甜蜜烦恼,就是当线上业务规模越来越大,系统分支发展越来越多的时候,初 ...