单例模式:确保一个类有且仅有一个实例
vs2015
win10 64位
非线程安全、基于继承实现
template <class T>
class Singleton
{
public:
	Singleton()
	{
		assert(!m_pT);
		m_pT = static_cast<T*>(this);
	}
	virtual ~Singleton()
	{
		assert(m_pT);
		m_pT = nullptr;
	}
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
public:
	static T* GetInstancePtr()
	{
		return m_pT;
	}
private:
	static T* m_pT;
};
template <class T> T*  Singleton<T>::m_pT = nullptr;
class CSingleTest : public Singleton<CSingleTest>
{
};
{
	CSingleTest objSingleTest;
}
非继承实现、手动释放资源
template <class T>
class CSingleton
{
public:
	template<typename... Args>
	static T* GetInstance(Args&&... args)
	{
		if (nullptr != m_ptrT)
		{
			return m_ptrT;
		}
		std::lock_guard<std::mutex> lock(m_mutex);
		if (nullptr != m_ptrT)
		{
			return m_ptrT;
		}
		m_ptrT = new T(std::forward<Args>(args)...);
		return m_ptrT;
	}
	static void ReleaseInstance()
	{
		if (nullptr == m_ptrT)
		{
			return;
		}
		delete m_ptrT;
		m_ptrT = nullptr;
	}
	~CSingleton() = default;
private:
	CSingleton() {}
	CSingleton(const CSingleton&) = delete;
	CSingleton& operator=(const CSingleton&) = delete;
private:
	static T* m_ptrT;
	static std::mutex m_mutex;
};
template<class T> T* CSingleton<T>::m_ptrT = nullptr;
template<class T> std::mutex CSingleton<T>::m_mutex;
非继承实现
template <class T>
class CSingleton
{
public:
	template<typename... Args>
	static T* GetInstance(Args&&... args)
	{
		if (nullptr != m_ptrT)
		{
			return &(*m_ptrT);
		}
		std::lock_guard<std::mutex> lock(m_mutex);
		if (nullptr != m_ptrT)
		{
			return &(*m_ptrT);
		}
		m_ptrT.reset(new T(std::forward<Args>(args)...));
		return &(*m_ptrT);
	}
	~CSingleton() = default;
private:
	CSingleton() {}
	CSingleton(const CSingleton&) = delete;
	CSingleton& operator=(const CSingleton&) = delete;
private:
	static std::unique_ptr<T> m_ptrT;
	static std::mutex m_mutex;
};
template<class T> std::unique_ptr<T> CSingleton<T>::m_ptrT = nullptr;
template<class T> std::mutex CSingleton<T>::m_mutex;
静态局部变量示例
template <class T>
class CSingleton
{
public:
	static T* GetInstance()
	{
		static T instance();
		return &instance;
	}
	~CSingleton() = default;
private:
	CSingleton() {}
	CSingleton(const CSingleton&) = delete;
	CSingleton& operator=(const CSingleton&) = delete;
};
测试代码示例:
class CSingleTest
{
public:
	CSingleTest()
	{
		cout << "CSingleTest()" << endl;
	}
	CSingleTest(int nTmp)
	{
		cout << "CSingleTest(int nTmp)" << endl;
	}
	CSingleTest(int nTmp, string strName)
	{
		cout << "CSingleTest(int nTmp,string strName)" << endl;
	}
	~CSingleTest()
	{
		cout << "~CSingleTest()" << endl;
	}
	void Test()
	{
		cout << "Test()" << endl;
		cout << (void*)this << endl;
	}
};
int main()
{
	{
		CSingleton<CSingleTest>::GetInstance()->Test();
		CSingleton<CSingleTest>::GetInstance(10)->Test();
		CSingleton<CSingleTest>::GetInstance(10,"singleton")->Test();
	}
	system("pause");
    return 0;
}
上述4种实现各有优缺点
第1种:非线程安全、基于继承实现
在多线程的情况下不能保证只有一个实例,但是可以阻止实例间的复制拷贝、复制赋值操作,运行期多创建实例触发断言
第2种:非继承实现、手动释放资源
调用方式CSingleton<CSingleTest>::GetInstance()
这种实现增加了线程安全(著名的解决方案DCLP Double-Checked Locking Pattern,也并非线程安全)使用两次判断来解决线程安全问题并且提高效率
增加了可以选择合适构造函数进行初始化,解决了多种类型的单例可能需要创建多个类型的单例
所持有的资源必须手动释放
不会阻止实例间的复制拷贝、复制赋值操作
关于DCLP的分析可以参考Scott Meyers 和 Andrei Alexandrescu写的《C++ and the Perils of Double-Checked Locking》
第3种:在第2种方案上增加了非手动释放资源
第4种:改用局部静态变量
这种实现可以保证线程安全,不论在window平台下还是Linux平台下(取决于所使用的编译器),同时满足多种类型的单例可能需要创建多个类型的单例,但是每次获取时都需要加锁,效率上损失,以我所在的平台为例,下面是程序运行到static T instance(std::forward<Args>(args)...);时要执行的代码:
 // Control access to the initialization expression.  Only one thread may leave
 // this function before the variable has completed initialization, this thread
 // will perform initialization.  All other threads are blocked until the
 // initialization completes or fails due to an exception.
 extern "C" void __cdecl _Init_thread_header(int* const pOnce)
 {
     _Init_thread_lock();
	
     if (*pOnce == Uninitialized)
     {
         *pOnce = BeingInitialized;
     }
     else
     {
         while (*pOnce == BeingInitialized)
         {
             // Timeout can be replaced with an infinite wait when XP support is
             // removed or the XP-based condition variable is sophisticated enough
             // to guarantee all waiting threads will be woken when the variable is
             // signalled.
             _Init_thread_wait(XpTimeout);
	
             if (*pOnce == Uninitialized)
             {
                 *pOnce = BeingInitialized;
                 _Init_thread_unlock();
                 return;
             } 
         }
         _Init_thread_epoch = _Init_global_epoch;
     }
	
     _Init_thread_unlock();
 }
更多关于局部静态变量的线程安全问题可以参考这个解释,或者这篇文章, 上述第2、3、4种实现方式不会阻止实例间的复制拷贝、复制赋值操作,若想阻止这些操作可以借助boost库的类noncopyable或者自己实现一个类似的noncopyable