C++单例模式

单例模式

什么是单例模式

单例是设计模式里面的一种,全局有且只有一个类的static实例,在程序任何地方都能够调用到。单例模式分为懒汉模式(线程不安全)和饿汉模式;

懒汉模式

因为很懒,所以在调用方法的时候去new对象,多线程中是不安全的,需要加锁;

普通指针的懒汉模式(线程安全的,需要手动释放空间)

需要自己手动delete去释放空间;

#include <iostream>
#include <mutex>

//使用加锁的方式保证线程安全
class SingleInstance
{
public:
	~SingleInstance()
	{
		std::cout << "析构函数" << std::endl;
	}
    SingleInstance(const SingleInstance&) = delete;
	SingleInstance& operator =(const SingleInstance) = delete;
	static SingleInstance* GetSingleInstance()
	{
		std::cout << "GetSingleInstance" << std::endl;
		if (m_SingleInstance == nullptr)
		{
			//上锁
			std::lock_guard<std::mutex> lk(m_mutex);
			//双重判断
			if (m_SingleInstance == nullptr)
			{
				m_SingleInstance = new SingleInstance();
			}
		}
		return m_SingleInstance;
	}

private:
	explicit SingleInstance()
	{
		std::cout << "构造函数" << std::endl;
	}

private:
	static SingleInstance* m_SingleInstance;
	static std::mutex m_mutex;
};

//初始化
SingleInstance* SingleInstance::m_SingleInstance = nullptr;
std::mutex SingleInstance::m_mutex;

智能指针的懒汉模式(线程安全的)

因为使用了智能指针,所以不需要手动delete去释放空间;

#include <iostream>
#include <mutex>

//使用加锁的方式保证线程安全
class SingleInstance
{
public:
	~SingleInstance()
	{
		std::cout << "析构函数" << std::endl;
	}
    SingleInstance(const SingleInstance&) = delete;
	SingleInstance& operator =(const SingleInstance) = delete;
	static std::shared_ptr<SingleInstance> GetSingleInstance()
	{
		std::cout << "GetSingleInstance" << std::endl;
		if (m_SingleInstance == nullptr)
		{
			//上锁
			std::lock_guard<std::mutex> lk(m_mutex);
			//双重判断
			if (m_SingleInstance == nullptr)
			{
				m_SingleInstance = std::shared_ptr<SingleInstance>(new SingleInstance());
			}
		}
		return m_SingleInstance;
	}

private:
	explicit SingleInstance()
	{
		std::cout << "构造函数" << std::endl;
	}

private:
	static std::shared_ptr<SingleInstance> m_SingleInstance;
	static std::mutex m_mutex;
};

//初始化
std::shared_ptr<SingleInstance> SingleInstance::m_SingleInstance = nullptr;
std::mutex SingleInstance::m_mutex;

局部静态懒汉模式(推荐)

最推荐,最简洁,最安全的方式

这种方法又叫做 Meyers’ SingletonMeyer’s的单例, 是著名的写出《Effective C++》系列书籍的作者 Meyers 提出的。所用到的特性是在C++11标准中的Magic Static特性:

#include <iostream>

class SingleInstance
{
public:
	~SingleInstance()
	{
		std::cout << "析构函数" << std::endl;
	}

	SingleInstance(const SingleInstance&) = delete;
	SingleInstance& operator =(const SingleInstance) = delete;

	static SingleInstance& GetSingleInstance()
	{
		static SingleInstance m_SingleInstance;
		return m_SingleInstance;
	}

private:
	explicit SingleInstance()
	{
		std::cout << "构造函数" << std::endl;
	}

private:
};

饿汉模式(手动释放)

因为已经饿的不行了,所以直接new了一个空间,线程也是安全的

#include <iostream>

class SingleInstance
{
public:
	~SingleInstance()
	{
		std::cout << "析构函数" << std::endl;
	}

	SingleInstance(const SingleInstance&) = delete;
	SingleInstance& operator =(const SingleInstance) = delete;

	static SingleInstance* GetSingleInstance()
	{
		return m_SingleInstance;
	}

private:
	explicit SingleInstance()
	{
		std::cout << "构造函数" << std::endl;
	}

private:
	static SingleInstance *m_SingleInstance;
};

SingleInstance* SingleInstance::m_SingleInstance = new SingleInstance();

其他的版本与懒汉类似

应该在什么时候下使用单例模式?

举一个小例子,在我们的windows桌面上,我们打开了一个回收站,当我们试图再次打开一个新的回收站时,Windows系统并不会为你弹出一个新的回收站窗口。,也就是说在整个系统运行的过程中,系统只维护一个回收站的实例。这就是一个典型的单例模式运用。

继续说回收站,我们在实际使用中并不存在需要同时打开两个回收站窗口的必要性。假如我每次创建回收站时都需要消耗大量的资源,而每个回收站之间资源是共享的,那么在没有必要多次重复创建该实例的情况下,创建了多个实例,这样做就会给系统造成不必要的负担,造成资源浪费。

再举一个例子,网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值