Singleton模式的经典实现如下:
class Singleton
{
public:
static Singleton * GetInstance()
{
if( 0== m_instance)
{
m_instance = new Singleton;
}
return m_instance;
}
protected:
Singleton(void)
{
}
virtual ~Singleton(void)
{
}
static Singleton* m_instance;
};
实现虽然简单,但是潜在问题很多。
首先,为避免内存泄露,要注意回收资源,为了打到自动回收,可以用auto_ptr解决。
using namespace std;
class Singleton
{
public:
static Singleton * GetInstance()
{
if( 0== m_instance.get())
{
m_instance.reset( new Singleton);
}
return m_instance.get();
}
protected:
Singleton(void)
{
}
virtual ~Singleton(void)
{
}
friend class auto_ptr<Singleton>;
static auto_ptr<Singleton> m_instance;
};
//Singleton.cpp
auto_ptr<Singleton> Singleton::_instance;
其次也是很重要的就是多线程下的注意问题,《深入浅出设计模式》里面提到,当然是在Java的使用环境下,有三种解决方法,在第五章有解释。
这里,我们用C++再次诠释,当然还是最常用的double-check方法来保证单件模式的线程安全,代码用模板来做。
template <class T>
class Singleton
{
public:
static inline T* GetInstance();
private:
Singleton(void)
{
}
~Singleton(void)
{
}
Singleton(const Singleton&)
{
}
Singleton & operator= (const Singleton &)
{
}
static auto_ptr<T> m_instance;
static CLock m_lock;
};
template <class T>
auto_ptr<T> Singleton<T>::m_instance;
template <class T>
CLock Singleton<T>::m_lock;
template <class T>
inline T* Singleton<T>::GetInstance()
{
if( 0 == m_instance.get() )
{
CLock::Lock lock(m_lock);
if( 0== m_instance.get())
{
m_instance.reset ( new T);
}
}
return m_instance.get();
}
下面是CLock 的实现:
// 所有的成员函数都必须是线程安全的。
class CLock
{
public:
CLock() { m_lockCnt = 0; InitializeCriticalSection(&m_cs); }
~CLock() { DeleteCriticalSection(&m_cs); }
// IsGuarded is used for debugging
BOOL IsLocked() const { return(m_lGrdCnt > 0); }
public:
class Lock
{
public:
Lock(CLock & rg) : m_rg(rg) { m_rg.Locked(); };
~Lock() { m_rg.UnLocked(); }
private:
CLock & m_rg;
};
private:
void Locked()
{
EnterCriticalSection(&m_cs);
m_lockCnt++;
}
void UnLocked()
{
m_lockCnt--;
LeaveCriticalSection(&m_cs);
}
friend class CLock::Lock;
private:
CRITICAL_SECTION m_cs;
long m_lockCnt; // # of EnterCriticalSection calls
};
Reference : http://www.cppblog.com/dyj057/archive/2009/04/17/346.html