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

C++ 賦值運算子回傳 *this 參考深度解析:鏈式賦值、避免暫時物件、效能優化

     編輯:關於C++

經典 C++ 面試題:`operator=` 為什麼要回傳 `*this` 的參考?本文透過對比實驗,從物件模型、建構/解構開銷、鏈式賦值語意三個維度完整解析。

實驗程式碼

class A {
public:
    A(int n) : m_nTest(n) { cout << "建構(值) " << n << endl; }
    A(const A& a) : m_nTest(a.m_nTest) { cout << "複製建構" << endl; }
    A() { cout << "建構(預設)" << endl; }
    ~A() { cout << "解構" << endl; }
    
    // 版本一:回傳物件 (by value)
    A operator=(const A& a) {
        if (this == &a) return *this;
        m_nTest = a.m_nTest;
        cout << "指派" << endl;
        return *this;  // 觸發複製建構
    }
    
    // 版本二:回傳參考
    // A& operator=(const A& a) { ... return *this; }
    
    void print() { cout << m_nTest << endl; }
private:
    int m_nTest;
};

int main() {
    A a(100), b(99), c(98);
    a = b = c;  // 右結合:a.operator=(b.operator=(c))
    a.print(); b.print(); c.print();
}

執行結果對比

版本一:回傳物件 (by value)

建構(值) 100
建構(值) 99
建構(值) 98
指派          // b = c
複製建構      // 產生暫時物件接收 b.operator= 回傳值
指派          // a = 暫時物件
複製建構      // 產生第二個暫時物件
解構          // 解構第一個暫時物件 (a= 的結果)
解構          // 解構第二個暫時物件 (b= 的結果)
99
99
98
解構 x3       // a,b,c 解構

額外開銷:2 次複製建構 + 2 次解構 = 2 個暫時物件完整生命週期。

版本二:回傳參考 (by reference)

建構(值) 100
建構(值) 99
建構(值) 98
指派          // b = c
指派          // a = b (直接操作 b 物件)
98
98
98
解構 x3

零暫時物件:參考只是別名,不觸發建構/解構。

深度機制解析

版本一發生了什麼?

  1. `b.operator=(c)` 執行指派,回傳 `*this` (即 `b`)
  2. 回傳值初始化暫時物件 `temp1` → **複製建構函數**
  3. `a.operator=(temp1)` 執行指派,回傳 `*this` (即 `a`)
  4. 回傳值初始化暫時物件 `temp2` → **複製建構函數**
  5. 完整表達式結束 (序列點) → **解構 `temp2` 再 `temp1`** (反序)

版本二為什麼快?

`A& operator=` 回傳 `A&`,參考綁定至原物件,**無新物件建立**。類似:

void func(A& ref) { ref... }  // 呼叫 func(a) 不產生暫時物件
A& ref = a;  // 別名綁定,零開銷

進階思考題

  1. (a=b)=c vs a=b=c:前者強制左結合,`a=b` 回傳參考直接賦值 `c`,無暫時物件;後者右結合同上分析。
  2. const A& operator=:可行但破壞鏈式賦值 (`(a=b)=c` 編譯錯誤,`const` 物件不可指派)。標準庫容器 `operator=` 回傳非 const 參考。
  3. return a vs return *this:語意錯誤!回傳右運算元參考會導致 `a=b=c` 讓 `a` 變成 `c` 的別名,後續修改 `a` 影響 `c`。
  4. A a; A b = a; (複製建構) vs A a,b; a=b; (指派):前者單次複製建構;後者預設建構 + 指派。資源管理類別 (RAII) 差異巨大。

最佳實踐總結

class MyClass {
public:
    // 標準規範形式
    MyClass& operator=(const MyClass& other) {
        if (this != &other) {
            // 1. 釋放舊資源
            // 2. 深層複製新資源
            // 3. 複製資料成員
        }
        return *this;  // 參考回傳:支援鏈式、零暫時物件、符合標準慣例
    }
    
    // C++11 移動指派
    MyClass& operator=(MyClass&& other) noexcept {
        if (this != &other) {
            // 移動資源所有權
        }
        return *this;
    }
};
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved