單例模式確保類別僅有一實例並提供全域存取點。本文針對日誌模組需求,演示四種主流實作版本:基本版、雙重檢查鎖版、靜態初始化版、區域靜態變數版,深度對比執行緒安全、效能、銷毀控制與適用場景。
class Singleton {
static Singleton *m_instance;
int m_test;
Singleton() : m_test(10) {}
public:
static Singleton* GetInstance() {
if (!m_instance) m_instance = new Singleton();
return m_instance;
}
static void DestroyInstance() {
delete m_instance; m_instance = nullptr;
}
int GetTest() { return m_test; }
};
Singleton* Singleton::m_instance = nullptr;
❌ 多執行緒下可能建立多個實例。
static Singleton* GetInstance() {
if (!m_instance) {
Lock(); // 需外部庫(Boost/std::mutex)
if (!m_instance) m_instance = new Singleton();
UnLock();
}
return m_instance;
}
✅ 執行緒安全(雙重檢查減少鎖開銷)。
⚠️ 高併發下鎖競爭成為效能瓶頸。
⚠️ 需手動呼叫 DestroyInstance(),易忘記/時機難控。
class Singleton {
int m_test;
Singleton() : m_test(10) {}
public:
static Singleton* GetInstance() {
return const_cast<Singleton*>(m_instance);
}
static void DestroyInstance() { /* 同版本一 */ }
private:
static const Singleton *m_instance;
};
const Singleton* Singleton::m_instance = new Singleton(); // 主執行緒單執行緒初始化
✅ 靜態初始化發生在 main 前,主執行緒單執行緒完成,**天然執行緒安全**。
✅ 無鎖開銷,效能最佳。
⚠️ 實例建立時間提前(程式啟動時),若建構耗時影響啟動速度。
⚠️ 同樣需手動銷毀。
class Singleton {
int m_test;
Singleton() : m_test(10) {}
~Singleton() { cout << "Singleton destroyed" << endl; }
public:
static Singleton* GetInstance() {
static Singleton instance; // C++11 保證執行緒安全初始化
return &instance;
}
int GetTest() { return m_test++; }
// 無 DestroyInstance,由程式結束自動解構
};
✅ C++11 標準保證**執行緒安全初始化**(魔術靜態)。
✅ **首次使用時才建構**(Lazy Initialization),不影響啟動速度。
✅ **自動銷毀**(程式結束時按逆序解構),無記憶體洩漏風險。
✅ 程式碼最簡潔,現代 C++ **首選實作**。
| 維度 | 基本版 | 雙重檢查鎖 | 靜態初始化 | 區域靜態 (C++11) |
|---|---|---|---|---|
| 執行緒安全 | ❌ | ✅ | ✅ | ✅ |
| 同步開銷 | 無 | 首次有鎖 | 無 | 無 |
| 初始化時機 | 首次呼叫 | 首次呼叫 | 程式啟動 | 首次呼叫 |
| 銷毀控制 | 手動 | 手動 | 手動 | 自動 |
| 程式碼複雜度 | 低 | 中 | 中 | 極低 |
| 推薦等級 | ❌ | ⚠️ 旧專案 | ⚠️ 特定需求 | ✅✅✅ 標準 |
GetInstance()。GetInstance(),C++11 會拋出例外(避免未定義行為)。現代 C++(C++11 及以上)請**直接使用區域靜態變數版本**(Meyers Singleton)。它同時解決執行緒安全、延遲初始化、自動銷毀、程式碼極簡四大痛點。舊專案維護時,按相容性選擇雙重檢查鎖或靜態初始化版本。