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 已被刪除,對象處於無效狀態(異常安全性弱)。
Widget& operator=(Widget rhs) { // 參數按值傳遞,自動拷貝構造
swap(p, rhs.p); // 無拋交換
return *this; // rhs 析構釋放舊資源
}
優點:
1. 自然處理自我賦值(拷貝構造副本,交換後銷毀副本)。
2. **強異常安全**:拷貝失敗不修改 *this;交換不拋異常。
3. 代碼簡潔,復用拷貝構造與析構邏輯。
Widget& operator=(const Widget& rhs) {
int* old = p;
p = new int(*rhs.p); // 可能拋異常,但 old 仍有效
delete old;
return *this;
}
缺點:需確保 new 前不修改其他狀態,否則異常時對象不一致。
std::unique_ptr/shared_ptr 讓編譯器生成正確 operator=。a = a、a = b = c 等鏈式賦值場景。