首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C++ 單例模式深度解析:從 larbin 全局結構到線程安全實現

     編輯:關於C語言

單例模式是最廣為人知的設計模式之一,旨在確保一個類僅有一個實例並提供全局訪問點。本文從 larbin 專案中的全局結構體切入,層層遞進至經典的 C++ 單例實現,並探討資源釋放與線程安全問題。

1. larbin 中的全局結構體寫法

早期 C 風格常用結構體 + 靜態成員模擬單例:

// global.h
struct Global {
    Global();
    static int a;
    // ...
};

// global.cc
int Global::a = 0; // 靜態成員需類外定義

// main.cc 僅創建一個實例使用

缺點顯而易見:無構造函數私有化保護、無法控制初始化時機、銷毀順序不可控。

2. 經典單例模式(饿漢/懶漢與自動釋放)

C++ 單例通過私有構造函數、靜態實例指針、公有靜態獲取方法實現:

class Singleton {
public:
    static Singleton* GetInstance() {
        if (m_pInstance == nullptr)
            m_pInstance = new Singleton();
        return m_pInstance;
    }
private:
    Singleton() {}
    static Singleton* m_pInstance;
    
    // 內嵌垃圾回收類,確保程序結束時自動釋放
    class Garbo {
    public:
        ~Garbo() {
            if (Singleton::m_pInstance)
                delete Singleton::m_pInstance;
        }
    };
    static Garbo garbo; // 靜態成員,程序結束時析構
};

Singleton* Singleton::m_pInstance = nullptr;
Singleton::Garbo Singleton::garbo;

關鍵點:

  • 構造函數 private 防止外部實例化
  • 靜態指針 m_pInstance 持有唯一實例
  • 內嵌類 Garbo 的靜態實例 garbo 利用程序結束時自動析構特性釋放記憶體

3. 進階:線程安全與現代寫法

上述懶漢式在多線程下不安全。C++11 起可用 std::call_once 或局部靜態變數(Magic Static)實現線程安全:

class Singleton {
public:
    static Singleton& GetInstance() {
        static Singleton instance; // C++11 保證線程安全初始化
        return instance;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
private:
    Singleton() = default;
    ~Singleton() = default;
};

此寫法無需手動管理記憶體、無需 Garbo、天然線程安全、銷毀順序由編譯器保證。

4. 單例的適用場景與爭議

典型場景:日誌系統、配置管理、資源池、GUI 窗口管理器等。但濫用單例會導致全局狀態難測試、耦合度高、隱藏依賴。現代 C++ 傾向於依賴注入替代單例。

總結

從 C 風格全局結構到現代 C++ 線程安全單例,核心演進在於:封裝構造、控制生命週期、保證線程安全。根據項目標準選擇合適版本,切記「單例不等於全局變數」,謹慎使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved