1. 程式人生 > >C++ Singleton (單例) 模式最優實現

C++ Singleton (單例) 模式最優實現

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 大師有個更簡便的方法.