单例模式,是一种类的设计模式,采用单例模式设计的类,只允许有一个实例。


为什么要采用单例模式:

1、有些对象在程序的整个声明周期中,为了保证数据的正确性,只允许有一个实例。

2、节省资源

3、满足“低耦合”的设计



单例模式的实现:

单例模式有两种实现方式:懒汉模式、饿汉模式


懒汉模式:

//////////////////////////////////////////////////////////
//懒汉模式
class Signletom	
{
public:
	static Signletom* GetInstance()
	{
		static mutex _mtx; //锁子
		if (_sInstance == NULL)//优化:双重检查,避免过多的加锁解锁,提高效率
		{
			//_mtx. lock();
			lock_guard lock(_mtx);	//加锁,保证线程安全
			if (_sInstance == NULL)
			{
				//_sInstance = new Signletom();		//new抛异常的化,可能会死锁   可以改用lock_guard, 它采用RAII,类似智能指针,也就是:构造加锁,析构解锁
				Signletom *tmp = new Signletom();
				MemoryBarrier();							   //内存栅栏:作用:防止编译器的指令优化 (分配空间、构造函数、赋值 这三部必须严格按顺序进行)
				_sInstance = tmp;
			}
		}//_mtx.unlock();
		return _sInstance;
	}

	void Print()
	{
		cout << _a << endl;
	}
	 
protected:
	Signletom()    //构造函数写在里面
		:_a(0)
	{}

	Signletom(const Signletom*); //拷贝构造也写在里面,防止被调用
	Signletom& operator=(const Signletom&); //赋值操作符重载同上
protected:
	int _a;
	static Signletom *_sInstance;
};

Signletom* Signletom::_sInstance = NULL;


饿汉模式:

//////////////////////////////////////////////////////////
//饿汉模式
class SignletomHungry
{
public:
	static SignletomHungry* GetInstance()
	{	
		assert(_sInstance);
		return _sInstance;
	}

	void Print()
	{
		cout << _a << endl;
	}

protected:
	SignletomHungry()    //构造函数写在里面
		:_a(0)
	{}

	SignletomHungry(const SignletomHungry*); //拷贝构造也写在里面,防止被调用
	SignletomHungry& operator=(const SignletomHungry&); //赋值操作符重载同上
protected:
	int _a;
	static SignletomHungry *_sInstance;
};

//静态  和 全局的初始化是在main之前,这时只有一个主线程,因此是线程安全的
SignletomHungry* SignletomHungry::_sInstance = new SignletomHungry();