現在就單例模式的幾種實現方式進行比較:
1、最常見的單例寫法
使用static私有
變量,並提供一個靜態方法作為單例的接口。讓構造成為私有的,即該對象不能通過類外進行實例化。
class Singleton
{
public:
void myInfo();
static Singleton * getInstance();
private:
Singleton();
~Singleton();
static Singleton * m_sglton ;//(此處也可直接寫為靜態變量)
};
Singleton* Singleton:: m_sglton = NULL;//初始化在主線程之前
Singleton *Singleton::getInstance()
{
if(m_sglton == NULL)
{
m_sglton = new Singleton;
}
return sglton;
(返回對象)}
優點:簡單易於理解,缺點容易忘記釋放內存。
2、靜態局部變量的寫法
- 返回了靜態局部對象的指針
不用擔心內存釋放的問題,
class Singleton
{
public:
void myInfo();
static Singleton * getInstance();
private
Singleton();
~Singleton();
:
};
Singleton *Singleton::getInstance()
{
static Singleton siglton;
return &siglton;
}
- 返回靜態局對象的引用,由於擔心發生該對象的拷貝,將其拷貝構造和賦值構造改為私有函數。
class Singleton
{
public:
void myInfo();
static Singleton &getInstance();
private:
Singleton();
~Singleton();
Singleton(const Singleton &);
Singleton &operator =(const Singleton &);
};
Singleton &Singleton::getInstance()
{
static Singleton siglton;
return siglton;
}
Singleton test = Singleton::geInstance();這種情況出現時,編譯報錯。
線程安全問題:
當使用靜態局部變量,在多線程時,會出現線程安全問題,即線程重入。而靜態成員變量的寫法因為在main函數執行之前就已經進行了初始化,所以不必考慮線程安全問題。
- 對靜態局部變量采取線程安全的寫法(加鎖)
class Singleton
{
public:
void myInfo();
static Singleton &getInstance();
private:
Singleton();
~Singleton();
Singleton(const Singleton &);
Singleton &operator =(const Singleton &);
};
Singleton &Singleton::getInstance()
{
Lock();
static Singleton siglton;
UnLock();
return siglton;
}
發現問題
細心的讀者可能發現了一個問題,我在使用單例模式的時候,在其靜態成員函數中實例化了一個對象,該對象的私有構造函數得到執行(非靜態成員函數執行)。這與靜態函數不能調用類的非靜態成員規則矛盾嗎?
下一篇《
靜態成員函數與
私有構造函數與》將會對這塊內容進行探索!