C++ Singleton (單例) 模式最優實現
阿新 • • 發佈:2019-01-28
J. Nakamura 把它叫作 "Gamma Singleton", 因為這是 Gamma 在他大名鼎鼎的 <<設計模式>> (<<Design Patterns>>) [Gamma] 一書採用的方法. 稱它為 "懶漢模式" 是因為單例例項只在第一次被使用時進行初始化:
class Log { public: static Log* Instance() { if (!m_pInstance) m_pInstance = new Log; return m_pInstance; } virtual void Write(char const *logline); virtual bool SaveTo(char const *filename); private: Log(); // ctor is hidden Log(Log const&); // copy ctor is hidden static Log* m_pInstance; static std::list<std::string> m_data; }; // in log.cpp we have to add Log* Log::m_pInstance = NULL;
Instance() 只在第一次被呼叫時為 m_pInstance 分配記憶體並初始化. 嗯, 看上去所有的問題都解決了, 初始化順序有保證, 多型也沒問題.
不過細心的你可能已經發現了一個問題, 程式退出時, 解構函式沒被執行. 這在某些設計不可靠的系統上會導致資源洩漏, 比如檔案控制代碼, socket 連線, 記憶體等等. 幸好 Linux / Windows 2000/XP 等常用系統都能在程式退出時自動釋放佔用的系統資源. 不過這仍然可能是個隱患, 至少 J. Nakamura 印象中, 有些系統是不會自動釋放的.
對於這個問題, 比較土的解決方法是, 給每個 Singleton 類新增一個 destructor()
virtual bool destructor() { // ... release resource if (NULL!= m_pInstance) { delete m_pInstance; m_pInstance = NULL; } }
然後在程式退出時確保呼叫了每個 Singleton 類的 destructor() 方法, 這麼做雖然可靠, 但卻很是繁瑣. 幸運的是, Meyers 大師有個更簡便的方法.