單例模式是一種建立型的設計模式(creational design patterns),使用單例模式進行設計的類在程式中只擁有乙個例項(single instance),這個類稱為單例類,它會提供乙個全域性的訪問入口(global access point),關於單例模式的討論可以參考singleton revisited;基於這兩個特點,單例模式可以有以下幾種實現:
scott meyers 在 effective c++ 的 item 4: make sure that objects are initialized before they're used 裡面提出了一種利用 c++ 的static
關鍵字來實現的單例模式,這種實現非常簡潔高效,它的特點是:
僅當程式第一次執行到getinstance
函式時,執行instance
物件的初始化;
在 c++ 11 之後,被static
修飾的變數可以保證是執行緒安全的;
templateclass singleton
singleton(t&&) = delete;
singleton(const t&) = delete;
void operator= (const t&) = delete;
protected:
singleton() = default;
virtual ~singleton() = default;
};
通過禁用單例類的 copy constructor,move constructor 和 operator= 可以防止類的唯一例項被拷貝或移動;不暴露單例類的 constructor 和 destructor 可以保證單例類不會通過其他途徑被例項化,同時將兩者定義為 protected 可以讓其被子類繼承並使用。
lazy singleton 是一種比較傳統的實現方法,通過其名字可以看出來它也具有 lazy-evaluation 的特點,但在實現的時候需要考慮執行緒安全的問題:
templateclass lazysingleton
if (t_ == nullptr)
}lazysingleton(t&&) = delete;
lazysingleton(const t&) = delete;
void operator= (const t&) = delete;
protected:
lazysingleton() = default;
virtual ~lazysingleton() = default;
};templateunique_ptrlazysingleton::t_;
templatemutex lazysingleton::mtx_;
我們通過模板引數is_thread_safe
來控制這個類是否是執行緒安全的,因為在某些場景下我們會希望每個執行緒擁有乙個例項:
當is_thread_safe == false
,即非執行緒安全時,我們在getinstance
函式中直接判斷,初始化並返回單例物件;這裡使用了unique_ptr
防止執行緒銷毀時發生記憶體洩漏,也可以在析構函式中銷毀指標;
當is_thread_safe == true
時,我們通過 double-checked locking 來進行檢查並加鎖,防止單例類在每個執行緒上都被例項化。
和 lazy singleton 相反,eager singleton 利用 static member variable 的特性,在程式進入 main 函式之前進行初始化,這樣就繞開了執行緒安全的問題:
templateclass eagersingleton
eagersingleton(t&&) = delete;
eagersingleton(const t&) = delete;
void operator= (const t&) = delete;
protected:
eagersingleton() = default;
virtual ~eagersingleton() = default;
};templatet* eagersingleton::t_ = new (std::nothrow) t;
但是它也有兩個問題:
即使單例物件不被使用,單例類物件也會進行初始化;
static initialization order fiasco,即 t_ 物件和getinstance
函式的初始化先後順序是不固定的;
將上面實現的四種 singleton 分別繼承下來作為 functor 傳入執行緒物件進行測試:
class foo : public singleton
};class lazyfoo : public lazysingleton
};class threadsafelazyfoo : public lazysingleton
};class eagerfoo : public eagersingleton
};void singletontest()
輸出結果為:
0x60d110
0x60d110
0x7f92380008c0
0x7f92300008c0
0x7f92300008e0
0x7f92300008e0
0x1132010
0x1132010
可以看到只有第二組非執行緒安全的lazysingleton
在兩個執行緒中輸出的例項位址是不同的,其它的 singleton 均是執行緒安全的。
設計模式 單例模式之類模板實現
檔名稱 singletonobj.h 摘 要 單例模式,使用類模板 用法示例 declare singleton cdestobject 當前版本 1.0 作 者 fzuim 完成日期 2018年3月8日 pragma once templateclass csingletonobj csingle...
c 單例模式模板
所有單例模類直接繼承此模板即可,執行緒安全,效率高 無鎖 延時構造。include using namespace std template class singleton 禁止拷貝 singleton const singleton delete singleton operator const ...
c 多執行緒單例模式 C 單例模式實現
單例模式,可以說設計模式中最常應用的一種模式了。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全域性或者靜態變數的方式,這樣比較簡單,也是沒學過設計模式的人所能想到的最簡單的方式了。一般情況下,我們建立的一些類是屬於工具性質的,基本不用儲存太多...