c++ 單例模式
阿新 • • 發佈:2018-12-21
1.懶漢模式
在第一次用到類例項的時候才會去例項化
-
方法1:加鎖的經典懶漢實現
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* initance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::initance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
- 方法2:內部靜態變數的懶漢實現
在instance函式裡定義一個區域性的靜態例項,只在第一次執行時建立,所以也可以保證擁有唯一例項。
這裡最好加上鎖,如不加,可能造成執行緒不安全(depends on implementation: e.g. g++ will insert locks, but MSVC will not)。
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* initance(); int a; }; pthread_mutex_t singleton::mutex; singleton* singleton::initance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
2.餓漢模式
在進入main函式前就已經完成物件的定義和初始化,執行緒安全。
但是有隱患,因為c++中對全域性物件的構造順序並沒有明確的規定。假如有一個全域性物件A,其建構函式裡引用如下程式碼餓漢形式的指標,若在A建構函式構造之前以上單例並未構造出來,那就會有問題。
同時要注意,在建構函式裡使用其它類的成員變數,是危險行為。
class singleton { protected: singleton() {} private: static singleton* p; public: static singleton* initance(); }; singleton* singleton::p = new singleton; singleton* singleton::initance() { return p; }
3.單例模式的資源釋放
很多情況下資源的釋放是有必要的,如關閉佔用的檔案、斷開與伺服器的連線等等。
沒有使用new時,只需要在解構函式中釋放相關資源即可;
使用了new時,不能在解構函式中delete單例,這樣會造成delete和解構函式的迴圈呼叫,可以使用以下方法:
- 法1:寫一個函式,主動delete,缺點是容易忘記呼叫該函式。
- 法2:利用C++ Rall機制(resource acquisition is initialization,資源獲取即初始化),沒有深究到底是啥,大概就是程式在結束的時候,系統會自動析構所有的全域性變數,以及所有類的靜態成員變數。
class CSingleton:
{
public:
static CSingleton * GetInstance();
protected:
CSingleton();
private:
static CSingleton * m_pInstance;
class CGarbo // 它的唯一工作就是在解構函式中刪除CSingleton的例項
{
public:
~CGarbo()
{
if (CSingleton::m_pInstance)
delete CSingleton::m_pInstance;
}
};
static CGarbo Garbo; // 定義一個靜態成員,在程式結束時,系統會呼叫它的解構函式
}
參考: