c++单例模式的实现(懒汉和饿汉)

本文深入探讨了单例模式的设计理念及其实现方式,包括构造函数私有化、提供全局访问点等关键步骤,并通过示例代码展示了懒汉式与饿汉式的区别。此外,还讨论了如何解决多线程环境下单例模式的线程安全问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例模式(Singleton):

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

MFC编程中有且只有一个工具箱,只能启动一个任务管理器(win7),一个国家只有一个领导人等情景下应用。

怎么实现呢?

构造函数私有化,只有自己能调用构造函数;给外部提供一个获得指针的静态方法;提供全局访问点。

代码:

// SingletonPattern.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;

//临界区
class RAII_CrtcSec
{
private:
	CRITICAL_SECTION crtc_sec;
public:
	RAII_CrtcSec() { ::InitializeCriticalSection(&crtc_sec); }
	~RAII_CrtcSec() { ::DeleteCriticalSection(&crtc_sec); }
	RAII_CrtcSec(const RAII_CrtcSec &) = delete;
	RAII_CrtcSec & operator=(const RAII_CrtcSec &) = delete;

	//给数据上锁 防止多个线程同时访问
	void Lock() { ::EnterCriticalSection(&crtc_sec); }
	//去锁
	void Unlock() { ::LeaveCriticalSection(&crtc_sec); }
};
RAII_CrtcSec RC;

class Single
{
private:
	Single()
	{
		cout << "我被创建了!" << endl;
	}
	static Single *s;
public:
	static Single *GetInstance()
	{
		//不考虑多线程
		/*if (s == NULL)
		{
			s = new Single();
		}*/
		//考虑多线程
		//效率低  无论是否创建过 都要枷锁
		/*RC.Lock();
		if (s == NULL)       
		{
			s = new Single();
		}
		RC.Unlock();*/
		//效率更高
		if (s == NULL)  //如果没有被创建过 加锁  如果创建过 就不加锁
		{
			RC.Lock();
			if (s == NULL)
			{
				s = new Single();
			}	
			RC.Unlock();
		}
		
		return s;
	}
	void aaa()
	{
		cout << "我的地址:";
	}
};
Single* Single::s = NULL;
void creat()
{
	Single *s = Single::GetInstance();
	s->aaa();
	cout << s << endl;
}
int main()
{
	/*Single * t = Single::GetInstance();
	Single *tt = Single::GetInstance();
	cout << "指向同一地址:" << t << " " << tt << endl;*/
	//只能创建一次且地址相同,此时单例模式完成,但是对于多线程还是不行,测试如下:
	thread t1(creat);
	t1.detach();
	thread t2(creat);
	t2.detach();
	
	Sleep(1000);
	//发现被创建两次,且地址不同

	//使用临界区 互斥访问   结果 只实例化一次 且 地址相同  使用两次if判断效率更高
    return 0;
}

上面代码用到了c++11多线程、处理临界区变量的相关知识,还有不断优化的过程,注释很详细吗,就不多说了。

懒汉和饿汉:

懒汉:顾名思义,很懒,不到关键时刻不做事,也就是说第一次要用到这个类时才实例化。正是由于这一点,当多线程同时“第一次”访问这个类时,很容易出现问题,所以懒汉模式要考虑到线程安全的问题。

饿汉:就是特别饿,见到就要吃,吃的已经准备好了,也就是说这个类在程序一开始就实例化完成,放在那。

上面的代码很明显时懒汉模式,虽然早早地声明了,但是实例化是在GetInstance()方法中,第一次用到这个方法才实例化,。

那饿汉模式的代码又怎么写呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值