1. 程式人生 > >【C++】單例模式之C++實現

【C++】單例模式之C++實現

單例模式的概念

只允許一個產生一個物件的類

單例模式的實現方法

1.單例類保證全域性只有唯一一個自行建立的例項物件
2.單例類提供獲取這個唯一例項的介面

單例模式的優缺點

優點

(1)阻止其他度物件例項化自己的副本,保證所有訪問唯一性
(2)類控制了例項化的過程,所以可以靈活的更改例項化的過程

缺點

(1)每次都需要檢查是否物件已經生成,造成些微的開銷
(2)使用單例物件時,開發人員可能會意外發現自己無法例項化該類


單例模式的分類

懶漢模式(適用於各種場景)

在需要的時候建立物件
懶漢模式需要加入synchronized才可以保證執行緒安全

餓漢模式(在某些場景下受到限制)

在main函式開始的時候即建立物件

餓漢模式是執行緒安全的

程式碼實現

懶漢模式的實現

普通版本

class SingleTon
{
public:
	static SingleTon* GetInstance()//獲取物件例項的唯一介面
	{
		if (_inst == NULL)
		{
			_inst = new SingleTon;
		}
		return _inst;
	}

	void Print()
	{
		cout << "SingleTon : " << _a << endl;
	}

private:
	SingleTon()//防止建構函式建立物件
		:_a(0)
	{}

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

	int _a;
	static SingleTon* _inst;//指向例項化的指標定義成靜態成員
};

SingleTon* SingleTon::_inst = NULL;

執行緒安全版本

加入RAII機制,避免死鎖的出現

class SingleTon
{
public:
	static SingleTon* GetInstance()//獲取物件例項的唯一介面
	{
		if (NULL == _inst)//只有在建立例項的時候才進行加鎖提高效率
		{
			lock_guard<mutex>lock(_mtx);
			if (_inst == NULL)
			{
				_inst = new SingleTon;
			}
		}
		return _inst;
	}

	void Print()
	{
		cout << "SingleTon : " << _a << endl;
	}

private:
	SingleTon()//防止建構函式建立物件
		:_a(0)
	{}

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

	int _a;
	static SingleTon* _inst;//指向例項化的指標定義成靜態成員
	static mutex _mtx;//保證安全的互斥鎖
};

SingleTon* SingleTon::_inst = NULL;
mutex SingleTon::_mtx;

記憶體柵欄技術&單例物件的釋放

新增雙檢查機制來提高效率 新增記憶體柵欄技術來防止由於提升效率而打亂執行的順序 對單例模式的釋放,下面這種方法是有問題的 最好是呼叫atexit回撥機制,在main函式結束完畢後再進行釋放
class SingleTon
{
public:
	static SingleTon* GetInstance()//獲取物件例項的唯一介面
	{
		if (NULL == _inst)//只有在建立例項的時候才進行加鎖提高效率
		{
			lock_guard<mutex>lock(_mtx);

			if (_inst == NULL)
			{
				SingleTon* tmp = new SingleTon;
				MemoryBarrier();//記憶體柵欄技術
				_inst = tmp;
			}
		}
		return _inst;
	}

	void Print()
	{
		cout << "SingleTon : " << _inst << endl;
	}

	static void DellInstance()
	{
		lock_guard<mutex>lock(_mtx);

		if (_inst)
		{
			cout << "delete " << endl;
			delete _inst;
			_inst = NULL;
		}
	}

private:
	SingleTon()//防止建構函式建立物件
		:_a(0)
	{}

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

	int _a;
	static SingleTon* _inst;//指向例項化的指標定義成靜態成員
	static mutex _mtx;//保證安全的互斥鎖
};

SingleTon* SingleTon::_inst = NULL;
mutex SingleTon::_mtx;

餓漢模式的實現

簡潔,高效,不用加鎖

但是在特定情況下會出現問題

實現方法1

class Singleton
{
public:
	static Singleton& GetInstance()
	{
		assert(_inst);
		return *_inst;
	}

	void Print()
	{
		cout << "Singleton : " << _inst << endl;
	}
private:
	Singleton()
		:_a(0)
	{}

	int _a;
	Singleton& operator=(const Singleton&) = delete;
	Singleton(const Singleton&) = delete;

	static Singleton* _inst;
};

Singleton* Singleton::_inst = new Singleton;

實現方法2

class Singleton
{
public:
	static Singleton& GetInstance()
	{
		static Single _inst;
		return *_inst;
	}

	void Print()
	{
		cout << "Singleton : " << _inst << endl;
	}
private:
	Singleton()
		:_a(0)
	{}

	int _a;
	Singleton& operator=(const Singleton&) = delete;
	Singleton(const Singleton&) = delete;

	static Singleton* _inst;
};

Singleton* Singleton::_inst = NULL;