首页 > 代码库 > 单例使用比较

单例使用比较

服务器程序里很多时候都需要使用单例,目前我使用有两种方式:

方式一:

	static CWanClient& Instance()
	{
		static CWanClient m_cWanClient;
		return m_cWanClient;
	}

静态成员方式调用,看上去也没什么问题


方式二:

	
	/*
	*	使用的时候只需要单件类继承此模板即可。
	*	class CTest : public Singleton<CTest>
	*	{...};      
	*
	*	程序退出时需要调用Release()释放指针
	*/ 
	template<class T>
	class Singleton
	{
	  private:
		/**
		 * \brief 拷贝构造函数,没有实现,禁用掉了
		 *
		 */
		Singleton(const Singleton&);

		/**
		 * \brief 赋值操作符号,没有实现,禁用掉了
		 *
		 */
		const Singleton & operator= (const Singleton &);
	public:
		static T* GetMe()
		{
			if (!_instance)
			{
				_instance = new T;
			}
			return _instance;
		}

		static void Release()
		{
			if ( NULL != _instance )
			{
				delete _instance;
				_instance = NULL;
			}
		}
	protected:
		// 使用保护构造是为了用户不能在栈上声明一个实例
		Singleton() {}
	private:
		static T* _instance;		// 实例静态指针
	};

	// 静态实例指针初始化
	template <class T> T* Singleton<T>::_instance = NULL; 

使用时:

class CWanClient : public Singleton<CWanClient>

两种方式一看就明白,第二种方式是new出来的对象,需要手动释放。


这两种方式的代码若是放在exe中,好像区别不太大,也就是存储位置不一样,但是如果放在作为dll被调用时,问题就来了,

很多DLL调用方式,都期望接口是 new/delete (分配/释放),这时,如果使用的是第一种静态成员的方式,则就会导致重复调用此dll时,不会再次进入对像的构造和析构函数了。


后面想了想,这也是需要看实际情况来处理,若所有的初始化和释放都是单独的函数,并非构造和析构,那应该是没有问题的,手动调用就行了,但是当工程越来越大,DLL库越来越多的时候,这样的问题就很难查出来了,再者说,如果使用NEW方式的单例,是否还能避免栈溢出呢?


得出总结,还是使用new方式的单例更靠谱一些,无非多了一次手动释放而已。

单例使用比较