当前位置: 首页 > news >正文

C++单例模式实例

定义:在某些情况下,我们设计中的对象只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表对象、日志对象、充当打印机、显卡等设备的驱动程序的对象等。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生。
这里要说的单件模式就能确保一个类只有一个实例,并提供一个全局访问点。
在C++中实现如下:
实现1:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     static void cleanInstance();
 9     int getValue();
10     void setValue(int iValue);
11 private:
12     int m_iValue;
13     static CSingleton* m_pSingleton;
14     CSingleton();
15     ~CSingleton();
16 };
17  
18 CSingleton* CSingleton::m_pSingleton = NULL;
19  
20 CSingleton::CSingleton()
21 {
22     cout << "Constructor" << endl;
23 }
24  
25 CSingleton::~CSingleton()
26 {
27     cout << "Destructor" << endl;
28 }
29  
30 CSingleton* CSingleton::getInstance()
31 {
32     if (NULL == m_pSingleton)
33     {
34         m_pSingleton = new CSingleton();
35     }
36     return m_pSingleton;
37 }
38  
39 void CSingleton::cleanInstance()
40 {
41     delete m_pSingleton; m_pSingleton = NULL;
42 }
43  
44 int CSingleton::getValue()
45 {
46     return m_iValue;
47 }
48  
49 void CSingleton::setValue(int iValue)
50 {
51     m_iValue = iValue;
52 }
53  
54 int main()
55 {
56     CSingleton* pSingleton1 = CSingleton::getInstance();
57     CSingleton* pSingleton2 = CSingleton::getInstance();
58     pSingleton1->setValue(123);
59     if (pSingleton1->getValue() == pSingleton2->getValue())
60     {
61         cout << "Two objects is the same instance" << endl;
62     }
63     else
64     {
65         cout << "Two objects isn't the same instance" << endl;
66     }
67  
68     CSingleton::cleanInstance();
69     return 0;
70 }
相信大多数的同仁都喜欢使用上边这种单件模式的实现方法,如果在单线程的情况下,是没有问题的,但如果是多线程,那么就极有可能会返回两个不同的对象,在调用CSingleton::getInstance的时候,两个线程如果都同时运行完if判断,而又还没有调用到构造函数的话,想象下后果吧。那该怎么办呢?看下边这个实现吧。
实现2:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     static void cleanInstance();
 9     int getValue();
10     void setValue(int iValue);
11 private:
12     int m_iValue;
13     static CSingleton* m_pSingleton;
14     CSingleton();
15     ~CSingleton();
16 };
17  
18 // 在进程运行开始就实例化该单件,又称“急切”创建实例
19 CSingleton* CSingleton::m_pSingleton = new CSingleton();
20  
21 CSingleton::CSingleton()
22 {
23     cout << "Constructor" << endl;
24 }
25  
26 CSingleton::~CSingleton()
27 {
28     cout << "Destructor" << endl;
29 }
30  
31 CSingleton* CSingleton::getInstance()
32 {
33     return m_pSingleton;
34 }
35  
36 void CSingleton::cleanInstance()
37 {
38     delete m_pSingleton; m_pSingleton = NULL;
39 }
40  
41 int CSingleton::getValue()
42 {
43     return m_iValue;
44 }
45  
46 void CSingleton::setValue(int iValue)
47 {
48     m_iValue = iValue;
49 }
50  
51 int main()
52 {
53     CSingleton* pSingleton1 = CSingleton::getInstance();
54     CSingleton* pSingleton2 = CSingleton::getInstance();
55     pSingleton1->setValue(123);
56     if (pSingleton1->getValue() == pSingleton2->getValue())
57     {
58         cout << "Two objects is the same instance" << endl;
59     }
60     else
61     {
62         cout << "Two objects isn't the same instance" << endl;
63     }
64  
65     CSingleton::cleanInstance();
66     return 0;
67 }
哈哈,看清楚了吗?就是在进程运行的时候就对这个单件进行实例化,可是这样似乎又不能达到延迟实例化的目的啦。如果我们的对象对资源占用非常大,而我们的进行在整个过程中其实并没有用到这个单件,那岂不是白白浪费资源了嘛。还有更好的办法。
实现3:
 1 #include <iostream>
 2 using namespace std;
 3  
 4 class CSingleton
 5 {
 6 public:
 7     static CSingleton* getInstance();
 8     int getValue();
 9     void setValue(int iValue);
10 private:
11     int m_iValue;
12     CSingleton();
13     ~CSingleton();
14 };
15  
16 CSingleton::CSingleton()
17 {
18     cout << "Constructor" << endl;
19 }
20  
21 CSingleton::~CSingleton()
22 {
23     cout << "Destructor" << endl;
24 }
25  
26 CSingleton* CSingleton::getInstance()
27 {
28     static CSingleton single;
29     return &single;
30 }
31  
32 int CSingleton::getValue()
33 {
34     return m_iValue;
35 }
36  
37 void CSingleton::setValue(int iValue)
38 {
39     m_iValue = iValue;
40 }
41  
42 int main()
43 {
44     cout << "Process begin" << endl;
45     CSingleton* pSingleton1 = CSingleton::getInstance();
46     CSingleton* pSingleton2 = CSingleton::getInstance();
47     pSingleton1->setValue(123);
48     if (pSingleton1->getValue() == pSingleton2->getValue())
49     {
50         cout << "Two objects is the same instance" << endl;
51     }
52     else
53     {
54         cout << "Two objects isn't the same instance" << endl;
55     }
56     return 0;
57 }
看下运行结果吧:

Process begin
Constructor
Two objects is the same instance
Destructor

是不是跟预想的一样呢?把单件声明为成员函数中的静态成员,这样既可以达到延迟实例化的目的,又能达到线程安全的目的,而且看结果的最后,是不是在程序退出的时候,还自动的调用了析构函数呢?这样我们就可以把资源的释放放到析构函数里边,等到程序退出的时候,进程会自动释放这些静态成员的。

转载于:https://www.cnblogs.com/berlin-sun/p/CSingleton.html

相关文章:

  • Action(8):Error -27728:Step download timeout(120 seconds)has expired when downloading
  • 千位数减百位数不退位 区间代换
  • C# 第三次作业
  • Maven常用命令总结
  • ecshop开发日志之手机端虚拟商品自动发货
  • C++ 指针悬挂和赋值操作符的重载,拷贝构造函数实现
  • WCF-终结点之消息路由示例
  • Android学习笔记(四六):互联网通信-文件下载
  • 封装WebService的APM为Async、Await模式利于Asp.Net页面调用
  • Solr入门之SolrServer实例化方式
  • matlab mex 小o -o 出错
  • linux下的权限控制
  • java项目在linux上的运行
  • Dev的WPF控件与VS2012不兼容问题
  • [转]ARM Linux 3.x Device Tree Usage
  • axios 和 cookie 的那些事
  • canvas绘制圆角头像
  • EOS是什么
  • Java应用性能调优
  • LeetCode刷题——29. Divide Two Integers(Part 1靠自己)
  • mockjs让前端开发独立于后端
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • React16时代,该用什么姿势写 React ?
  • Sass Day-01
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Vultr 教程目录
  • WePY 在小程序性能调优上做出的探究
  • yii2权限控制rbac之rule详细讲解
  • 闭包--闭包之tab栏切换(四)
  • 从零开始的webpack生活-0x009:FilesLoader装载文件
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 我的业余项目总结
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 你对linux中grep命令知道多少?
  • 教程:使用iPhone相机和openCV来完成3D重建(第一部分) ...
  • 我们雇佣了一只大猴子...
  • ​力扣解法汇总946-验证栈序列
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1)Android开发优化---------UI优化
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (27)4.8 习题课
  • (4.10~4.16)
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (k8s中)docker netty OOM问题记录
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (四)库存超卖案例实战——优化redis分布式锁
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (一)认识微服务
  • (转)h264中avc和flv数据的解析
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • ***linux下安装xampp,XAMPP目录结构(阿里云安装xampp)
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .net core 微服务_.NET Core 3.0中用 Code-First 方式创建 gRPC 服务与客户端
  • .Net Core和.Net Standard直观理解
  • .net core使用RPC方式进行高效的HTTP服务访问