在 C++ 中實現單例模式有多種方法,以下是線程安全的現代 C++ 實現方式(推薦 C++11 及以上版本):
1. Meyers’ Singleton(推薦)
class Singleton {
public:// 刪除拷貝構造和賦值運算符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;static Singleton& getInstance() {static Singleton instance; // C++11 保證靜態局部變量線程安全return instance;}private:Singleton() = default; // 私有構造函數~Singleton() = default; // 私有析構函數
};
2. 傳統線程安全實現(雙重檢查鎖定)
#include <mutex>class Singleton {
public:static Singleton* getInstance() {if (instance == nullptr) {std::lock_guard<std::mutex> lock(mutex_);if (instance == nullptr) {instance = new Singleton();}}return instance;}// 刪除拷貝構造和賦值運算符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() = default;~Singleton() = default;static Singleton* instance;static std::mutex mutex_;
};// 初始化靜態成員
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex_;
3. 餓漢式(程序啟動時初始化)
class Singleton {
public:static Singleton& getInstance() {return instance;}// 刪除拷貝構造和賦值運算符Singleton(const Singleton&) = delete;Singleton& operator=(const Singleton&) = delete;private:Singleton() = default;~Singleton() = default;static Singleton instance;
};// 在源文件中初始化
Singleton Singleton::instance;
4.關鍵要素
- 私有構造函數:防止外部創建實例
- 刪除拷貝構造和賦值運算符:防止對象復制
- 靜態訪問方法:全局訪問點(
getInstance
) - 靜態實例指針/引用:保存唯一實例
- 線程安全:使用互斥鎖或 C++11 的線程安全靜態局部變量
5.使用方式
Singleton& instance = Singleton::getInstance();
6.注意事項
(1)推薦使用 Meyers’ Singleton(方法1),因為:
- 自動線程安全(C++11 標準保證)
- 自動內存管理(無需手動釋放)
- 延遲初始化(首次調用時創建)
如果需要繼承或更復雜控制,可以考慮智能指針實現
在程序結束時,靜態實例會由系統自動銷毀
避免在單例析構函數中引用其他可能已被銷毀的單例
(1)這兩種實現都滿足單例模式的三個核心要求:
- 保證唯一實例
- 提供全局訪問點
- 防止外部實例化