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

C++ 單例模式完整實作指南:從基礎到線程安全與自動釋放

     編輯:C++ 入門

單例模式核心意圖

確保類別全程式僅有一個實例,並提供全域存取點。適用於日誌系統、配置管理、資源池、硬體抽象層等場景。

演進歷程:五種實作等級

Level 1:樸素版(非線程安全)

class Singleton {
    static Singleton* instance_;
    Singleton() = default;
public:
    static Singleton* GetInstance() {
        if (!instance_) instance_ = new Singleton();
        return instance_;
    }
};
// 缺點:多線程競爭建立多實例;記憶體洩漏(無釋放機制)

Level 2:雙重檢查鎖定(DCLP,C++11 前手寫線程安全)

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 前極難);仍需手動釋放

Level 3:C++11 局部靜態變數(Meyers Singleton,推薦基礎版)

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;
    }
};
// 優點:標準保證線程安全、自動析構(程式結束時)、語法簡潔
// 缺點:析構順序跨翻譯單元不定;若析構函數有副作用需謹慎

Level 4:Garbo 內嵌類別(手動控制釋放時機,C++98/03 經典寫法)

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 邊界靜態析構順序風險

Level 5:現代 C++ 完美版(線程安全 + 智慧指標 + 自定義釋放)

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 自動釋放、可自定義刪除邏輯、防拷貝、支援多型(介面指標)。

關鍵設計決策對比表

常見反模式與避坑

  • ❌ 公開建構函數 → ✅ private/delete
  • ❌ 回傳裸指標且無釋放機制 → ✅ 回傳參考或智慧指標
  • ❌ 依賴跨翻譯單元靜態初始化順序 → ✅ 使用函數區域靜態變數
  • ❌ 單例濫用(全域狀態泛濫) → ✅ 僅用於真正「全域唯一資源」

現代 C++ 開發中,Meyers Singleton (Level 3) 覆蓋 90%+ 場景;特殊資源釋放需求時升級至 Level 5。拒絕手寫鎖、拒絕裸指標、拒絕記憶體洩漏。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求推薦方案關鍵技術
單執行緒、簡單專案Level 3C++11 static local
多執行緒、需自動釋放Level 3C++11 static local
需精確控制釋放時機/順序Level 5unique_ptr + custom deleter
跨 DLL 共享單例Level 5 + 介面隔離匯出介面、工廠函數
C++98/03 維護專案Level 4 + mutexGarbo + 雙重檢查鎖