單例銷毀 C 單例模式的模板實現

2021-10-15 00:23:24 字數 2914 閱讀 9774

單例模式是一種建立型的設計模式(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 單例模式實現

單例模式,可以說設計模式中最常應用的一種模式了。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全域性或者靜態變數的方式,這樣比較簡單,也是沒學過設計模式的人所能想到的最簡單的方式了。一般情況下,我們建立的一些類是屬於工具性質的,基本不用儲存太多...