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

Effective C++ 條款 11:在 operator= 中處理自我賦值

     編輯:關於C++

什麼是自我賦值

a = a、*p = *p、v[i] = v[j] (i==j) 等。若 operator= 內部先 delete 再 new,會導致釋放後再訪問已釋放內存(野指針)。

錯誤示範


class Widget {
    int* p;
public:
    Widget& operator=(const Widget& rhs) {
        delete p;           // 刪除自身資源!
        p = new int(*rhs.p); // rhs.p 可能已被刪除
        return *this;
    }
};

方案一:自我檢查


Widget& operator=(const Widget& rhs) {
    if (this == &rhs) return *this; // 早期返回
    delete p;
    p = new int(*rhs.p);
    return *this;
}

缺點:new 拋異常時,p 已被刪除,對象處於無效狀態(異常安全性弱)。

方案二:先拷貝後交換(Copy-and-Swap)


Widget& operator=(Widget rhs) { // 參數按值傳遞,自動拷貝構造
    swap(p, rhs.p);              // 無拋交換
    return *this;                // rhs 析構釋放舊資源
}

優點:
1. 自然處理自我賦值(拷貝構造副本,交換後銷毀副本)。
2. **強異常安全**:拷貝失敗不修改 *this;交換不拋異常。
3. 代碼簡潔,復用拷貝構造與析構邏輯。

方案三:手動保存舊指針(C++98 風格)


Widget& operator=(const Widget& rhs) {
    int* old = p;
    p = new int(*rhs.p); // 可能拋異常,但 old 仍有效
    delete old;
    return *this;
}

缺點:需確保 new 前不修改其他狀態,否則異常時對象不一致。

最佳實踐建議

  1. 優先使用 **Copy-and-Swap**(C++11 移動語義下更高效)。
  2. 若類管理多資源,考慮 std::unique_ptr/shared_ptr 讓編譯器生成正確 operator=。
  3. 總是測試 a = a、a = b = c 等鏈式賦值場景。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved