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

C++ 類別核心三大函式:建構、解構與指派詳解(下)— 複製建構與指派實戰

     編輯:VC 教學

9.3 建構與解構的順序

  • 建構順序:從繼承階層最基層(最基底類別)開始,每層先建構基底類別,再建構成員物件。
  • 解構順序:嚴格遵循建構的逆序,這是唯一確定的順序,否則編譯器無法自動執行解構。
  • 成員物件初始化順序:完全由類別宣告順序決定,與初始化列表中的書寫順序無關。因為類別宣告唯一,但建構函式可有多個(對應不同列表順序),若按列表順序建構將導致解構無法確定唯一逆序(參考 Eckel, pp. 260-261)。

9.4 實例:String 類別的建構與解構函式

// 一般建構函式
String::String(const char* str) {
    if (str == NULL) {
        m_data = new char[1];
        *m_data = '\0';
    } else {
        int length = strlen(str);
        m_data = new char[length + 1];
        strcpy(m_data, str);
    }
}

// 解構函式
String::~String() {
    delete[] m_data; // m_data 為內建型別指標,寫成 delete m_data 亦可
}

9.5 輕視不得:複製建構與指派函式

並非所有物件都會用到複製建構與指派,程式設計師容易輕視它們。請銘記以下警示:

陷阱一:預設「位拷貝」對指標成員是致命的

若類別含指標成員,編譯器生成的預設複製建構/指派函式會執行位元逐位拷貝(淺拷貝)。以 String a("hello"), b("world") 為例,執行 b = a 時:

  1. 記憶體洩漏:b.m_data 原有記憶體未釋放。
  2. 雙重指向:a.m_data 與 b.m_data 指向同一塊記憶體,任一方修改影響另一方。
  3. 雙重釋放:物件銷毀時 m_data 被 delete 兩次,導致未定義行為。

陷阱二:複製建構與指派極易混淆

  • 複製建構函式:物件建立時被呼叫。
  • 指派函式:已存在的物件才能呼叫。
String a("hello");
String b("world");
String c = a; // 呼叫複製建構函式,建議寫成 String c(a);
c = b;        // 呼叫指派函式

第三行寫法 String c = a 易與指派混淆,強烈建議改寫為 String c(a) 以明確語意。

9.6 實例:String 類別的複製建構與指派函式

// 複製建構函式
String::String(const String& other) {
    // 可存取 other 私有成員 m_data
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
}

// 指派函式
String& String::operator=(const String& other) {
    // (1) 檢查自我指派
    if (this == &other) return *this;
    
    // (2) 釋放原有記憶體
    delete[] m_data;
    
    // (3) 配置新記憶體並複製內容
    int length = strlen(other.m_data);
    m_data = new char[length + 1];
    strcpy(m_data, other.m_data);
    
    // (4) 回傳自身參考,支援鏈式指派 a = b = c
    return *this;
}

關鍵差異點

  • 複製建構函式無需檢查 NULL,因為「參考」絕不為 NULL,而「指標」可以。
  • 指派函式必須檢查自我指派,否則 delete[] m_data 會導致「自殺後仍嘗試複製」的災難。
  • 指派函式回傳 *this 而非 this 或 other,前者支援鏈式指派,後兩者皆錯誤(other 可能為暫時物件,生命週期不可控)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved