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

C++ 單例模式實作關鍵:私有拷貝建構子與賦值運算子

     編輯:關於VC++

問題背景

朋友實作單例類別 CSingleton,建構子設為 private,提供靜態 GetInstance() 回傳唯一實例參考。但以下程式碼編譯失敗:

CSingleton temp = CSingleton::GetInstance(); // 編譯錯誤

根本原因:編譯器隱式產生拷貝建構子

當編譯器遇到上述語句,會尋找拷貝建構子 CSingleton(const CSingleton&)。若使用者未自行宣告,編譯器會隱式產生 public 預設拷貝建構子(逐位元複製),導致單例保護機制失效。

解決方案:宣告私有拷貝建構子與賦值運算子

為徹底禁止複製,必須顯式宣告並設為 private:

class CSingleton {
public:
    static CSingleton& GetInstance() {
        static CSingleton theInstance; // 唯一實例,區域靜態變數確保執行緒安全 (C++11 起)
        return theInstance;
    }

protected:
    CSingleton() {} // 預設建構子,protected 允許繼承

private:
    // 關鍵:禁止複製與賦值
    CSingleton(const CSingleton&);             // 僅宣告,不定義(或定義為 ASSERT(FALSE))
    CSingleton& operator=(const CSingleton&); // 僅宣告,不定義
};

完整可編譯範例

class CSingleton {
public:
    static CSingleton& GetInstance() {
        static CSingleton theInstance;
        return theInstance;
    }

protected:
    CSingleton() {} // 需有預設建構子以建立實例

private:
    CSingleton(const CSingleton&) {}            // 私有拷貝建構子
    CSingleton& operator=(const CSingleton&) {} // 私有賦值運算子
};

int main() {
    // 以下皆編譯錯誤(私有拷貝/賦值)
    // CSingleton x = CSingleton::GetInstance(); // error
    // CSingleton y = CSingleton::GetInstance(); // error
    // x = y; // error

    // 正確用法:指標或參考
    CSingleton* p1 = &CSingleton::GetInstance();
    CSingleton* p2 = &CSingleton::GetInstance();
    CSingleton& ref = CSingleton::GetInstance();
    return 0;
}

單例實作三大原則

  1. 私有化:預設建構子、拷貝建構子、賦值運算子全設為 private (或 protected 允許繼承)
  2. 靜態存取:提供 static GetInstance() 回傳唯一實例參考/指標
  3. 區域靜態:函式內 static 變數確保延遲初始化與執行緒安全 (C++11 保證)

常見誤區提醒

  • 僅將建構子設為 private 不足夠,編譯器仍會產生 public 拷貝建構子
  • 若需繼承單例基類,建構子設為 protected,但拷貝/賦值仍需 private
  • C++11 起可用 = delete 明確刪除:CSingleton(const CSingleton&) = delete;

結語

正確實作單例模式的關鍵在於顯式封鎖所有複製路徑。理解編譯器隱式行為,才能寫出真正強健的單例類別。

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