談?wù)?C++ 單例模式

一個類只有一個實(shí)例化對象 全局可以使用
單例模式的基本實(shí)現(xiàn):包含單例模式的實(shí)現(xiàn),線程安全,以及生命周期等 單例模式的模板實(shí)現(xiàn), 多模塊調(diào)用單例存在的問題
單例模式的基本實(shí)現(xiàn)
私有的構(gòu)造函數(shù), 拷貝構(gòu)造函數(shù),以及 operator=, 保證其不能夠在類的外部進(jìn)程對象構(gòu)造,拷貝等操作。GetInstance是一個公有的靜態(tài)成員函數(shù),用來構(gòu)造這個類唯一的實(shí)例對象m_objConfig, 并且返回給使用者。
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig = = nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig *m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;
單例模式生命周期
單例創(chuàng)建的時機(jī)
class SingletonConfig{public:static SingletonConfig * GetInstance(){return m_objConfig;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig *m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = new SingletonConfig;
單例釋放的時機(jī)
class SingletonConfig{public:static SingletonConfig * GetInstance(){static SingletonConfig objConfig;return &objConfig;}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };};
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig == nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}static void ReleaseInstance(){if (m_objConfig){delete m_objConfig;m_objConfig = nullptr;}}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig* m_objConfig;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;
線程安全
static SingletonConfig * GetInstance(){static SingletonConfig objConfig;return &objConfig;}
static SingletonConfig * GetInstance(){if (m_objConfig == nullptr)m_objConfig = new SingletonConfig;return m_objConfig;}
使用 std::lock_guard去多線程保證互斥雙重的 m_objConfig == nullptr檢查,第一次是為了效率,當(dāng)單例對象已經(jīng)在的時候,就不需要互斥鎖了;第二次是進(jìn)入鎖范圍之后,要查看下,是否有其他線程已經(jīng)創(chuàng)建了單例對象,如果還沒有創(chuàng)建才進(jìn)行創(chuàng)建。
class SingletonConfig{public:static SingletonConfig * GetInstance(){if (m_objConfig == nullptr){std::lock_guard<std::mutex> guard(m_mutex);if (m_objConfig == nullptr){m_objConfig = new SingletonConfig;}}return m_objConfig;}static void ReleaseInstance(){if (m_objConfig){delete m_objConfig;m_objConfig = nullptr;}}virtual ~SingletonConfig(){std::cout << "~SingletonConfig()" << std::endl;}private:SingletonConfig() { ; };SingletonConfig(const SingletonConfig&) { ; };SingletonConfig& operator= (const SingletonConfig&) { ; };private:static SingletonConfig* m_objConfig;static std::mutex m_mutex;};SingletonConfig* SingletonConfig::m_objConfig = nullptr;std::mutex SingletonConfig::m_mutex;
單例模式的模板實(shí)現(xiàn)以及可能的問題
template<typename T>class CommonSingleton{public:static T* GetInstance(){if (m_objSingle == nullptr){std::lock_guard<std::mutex> guard(m_mutex);if (m_objSingle == nullptr){m_objSingle = new T;}}return m_objSingle;}static void ReleaseInstance(){if (m_objSingle){delete m_objSingle;m_objSingle = nullptr;}}private:CommonSingleton() { ; };CommonSingleton(const CommonSingleton&) { ; };CommonSingleton& operator= (const CommonSingleton&) { ; };private:static T* m_objSingle;static std::mutex m_mutex;};template<typename T>T* CommonSingleton::m_objSingle = nullptr; template<typename T>std::mutex CommonSingleton::m_mutex;
CommonSingleton<TestClass>::GetInstance();模板參數(shù)接受的類,可以是這種:默認(rèn)暴露給用戶,可以構(gòu)造,拷貝,賦值的類,這樣便可以重新創(chuàng)造多個對象。這種方式缺乏了本人所理解的 防御性編程的思路。當(dāng)使用模板實(shí)例化的時候,同一種模板參數(shù)的類,在多個不同的模塊中其實(shí)都會有自己的實(shí)例化對象。比如有A和B兩個模塊,并且均調(diào)用了 CommonSingleton, 其實(shí)在A和B中存在不同的::GetInstance(); TestClass對象,這樣也違背了一個程序一個實(shí)例化對象的初衷。當(dāng)然只有一個工程不影響。對于非模板的實(shí)現(xiàn),一般將單例實(shí)現(xiàn)的類從模塊導(dǎo)出,將實(shí)現(xiàn)放在.cpp文件中,那么這種多個工程對同一種單例的類只會有一個實(shí)例化對象。個人覺得這一點(diǎn)比較重要,需要讀者多多體會。
總結(jié)
參考
<中的Singletons實(shí)作技術(shù)這一章節(jié)> <<深入應(yīng)用C++11代碼優(yōu)化及工程級應(yīng)用>>的改進(jìn)單例模式這一章節(jié)
評論
圖片
表情

