確保類別全程式僅有一個實例,並提供全域存取點。適用於日誌系統、配置管理、資源池、硬體抽象層等場景。
class Singleton {
static Singleton* instance_;
Singleton() = default;
public:
static Singleton* GetInstance() {
if (!instance_) instance_ = new Singleton();
return instance_;
}
};
// 缺點:多線程競爭建立多實例;記憶體洩漏(無釋放機制)
class Singleton {
static Singleton* instance_;
static std::mutex mtx_;
Singleton() = default;
public:
static Singleton* GetInstance() {
if (!instance_) { // 第一次檢查(無鎖快速路徑)
std::lock_guard lock(mtx_);
if (!instance_) { // 第二次檢查(鎖內確認)
instance_ = new Singleton();
}
}
return instance_;
}
};
// 缺點:需正確處理記憶體順序(C++11 前極難);仍需手動釋放
class Singleton {
Singleton() = default;
~Singleton() = default;
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
public:
static Singleton& GetInstance() {
static Singleton instance; // C++11 保證線程安全、零開銷初始化
return instance;
}
};
// 優點:標準保證線程安全、自動析構(程式結束時)、語法簡潔
// 缺點:析構順序跨翻譯單元不定;若析構函數有副作用需謹慎
class Singleton {
static Singleton* instance_;
class Garbo { // 垃圾回收器
public:
~Garbo() { delete instance_; }
};
static Garbo garbo_; // 靜態成員,程式結束自動析構
Singleton() = default;
public:
static Singleton* GetInstance() {
if (!instance_) instance_ = new Singleton();
return instance_;
}
};
// 優點:明確控制釋放時機(main 結束前)、可在析構函數執行資源釋放邏輯
// 缺點:非線程安全;跨 DLL 邊界靜態析構順序風險
class Singleton {
Singleton() = default;
~Singleton() { /* 釋放資源:關檔、斷連線、釋放鎖 */ }
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
struct Deleter {
void operator()(Singleton* p) const {
delete p; // 可在這裡加入額外清理邏輯
}
};
public:
static std::unique_ptr& GetInstance() {
static std::unique_ptr instance(
new Singleton(), Deleter{}
);
return instance;
}
};
// 使用方式
Singleton::GetInstance()->DoWork();
優點:線程安全、RAII 自動釋放、可自定義刪除邏輯、防拷貝、支援多型(介面指標)。
| 需求 | 推薦方案 | 關鍵技術 |
|---|---|---|
| 單執行緒、簡單專案 | Level 3 | C++11 static local |
| 多執行緒、需自動釋放 | Level 3 | C++11 static local |
| 需精確控制釋放時機/順序 | Level 5 | unique_ptr + custom deleter |
| 跨 DLL 共享單例 | Level 5 + 介面隔離 | 匯出介面、工廠函數 |
| C++98/03 維護專案 | Level 4 + mutex | Garbo + 雙重檢查鎖 |