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

C++ 運算符重載:深入掌握賦值運算符與深拷貝實現

     編輯:關於C++

自定義類的賦值運算符重載函數功能類似內置賦值運算符,但與拷貝構造函數、析構函數一樣,必須嚴謹處理「深拷貝」與「淺拷貝」問題。若未顯式定義,編譯器會自動生成一個預設的賦值運算符重載函數,但這通常只能實現淺拷貝,對於包含指針成員的類極其危險。

賦值運算符重載的定義與關鍵點

賦值運算符重載函數的定義語法與其他運算符重載類似,通常返回類的引用(ClassName&)以支援鏈式賦值。核心邏輯在於:

  1. 釋放目標對象原有的動態分配資源(delete[])。
  2. 根據源對象重新分配記憶體。
  3. 執行深拷貝(逐字節複製數據)。
  4. 返回 *this。

完整代碼範例:Internet 類實現

#include <iostream>
#include <cstring>
using namespace std;

class Internet {
public:
    // 構造函數:動態分配字符串內存
    Internet(char *name, char *url) {
        this->name = new char[strlen(name) + 1];
        this->url = new char[strlen(url) + 1];
        if (name) strcpy(this->name, name);
        if (url) strcpy(this->url, url);
    }

    // 拷貝構造函數:深拷貝
    Internet(Internet &temp) {
        this->name = new char[strlen(temp.name) + 1];
        this->url = new char[strlen(temp.url) + 1];
        if (name) strcpy(this->name, temp.name);
        if (url) strcpy(this->url, temp.url);
    }

    // 析構函數:釋放資源
    ~Internet() {
        delete[] name;
        delete[] url;
    }

    // 賦值運算符重載:核心深拷貝邏輯
    Internet& operator=(Internet &temp) {
        // 1. 自賦值檢查(最佳實踐)
        if (this == &temp) return *this;

        // 2. 釋放原有資源
        delete[] this->name;
        delete[] this->url;

        // 3. 重新分配並深拷貝
        this->name = new char[strlen(temp.name) + 1];
        this->url = new char[strlen(temp.url) + 1];
        if (this->name) strcpy(this->name, temp.name);
        if (this->url) strcpy(this->url, temp.url);

        return *this;
    }

public:
    char *name;
    char *url;
};

int main() {
    Internet a("中國軟件開發實驗室", "www.cndev-lab.com");
    Internet b = a;      // 調用拷貝構造函數(對象不存在時)
    cout << b.name << endl << b.url << endl;

    Internet c("美國在線", "www.aol.com");
    b = c;               // 調用賦值運算符重載(對象已存在時)
    cout << b.name << endl << b.url << endl;

    system("pause");
    return 0;
}

關鍵區別:拷貝構造 vs 賦值運算符

  • 拷貝構造函數:在對象初始化時調用(如 Internet b = a;),對象尚未存在,直接構造。
  • 賦值運算符重載:在對象已存在時調用(如 b = c;),需先清理原有資源再複製新數據。

在賦值運算符中,delete[] 釋放指針指向的堆內存是解決深拷貝問題的關鍵。因為目標對象 b 已經構造過,其 name 和 url 指針已指向確定的堆區域,若不先釋放再分配,會導致記憶體洩漏或區域大小不匹配。

最佳實踐提醒

  1. 始終檢查自賦值(if (this == &rhs) return *this;)。
  2. 遵循「三法則」:若類需要自定義析構函數、拷貝構造函數或賦值運算符,通常三者都需要自定義(C++11 後擴展為「五法則」,加上移動構造與移動賦值)。
  3. 考慮使用 std::string 替代 char*,利用標準庫自動管理記憶體,避免手動深拷貝的錯誤風險。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved