C++ 自賦值
阿新 • • 發佈:2020-11-22
https://harttle.land/2015/07/30/effective-cpp-11.html,這個講的很不錯!
1.存在的問題
因為cpp中有指標和引用,它們可以指向同一個變數,所以會存在自賦值的問題。
a[i] = a[j]; //@ 如果i和j有同樣的值,這裡就是一次自賦值 *px = *py; //@ 如果px和py指向相同的東西,這裡就是一次自賦值
自賦值一般存在:自賦值安全和異常安全,兩個問題,例如:
自賦值安全:
Widget& Widget::operator=(const Widget& rhs){ delete pb; //stop using current bitmap pb = new Bitmap(*rhs.pb); // start using a copy of rhs's bitmap return *this; // see Item 10 }
當是自賦值的時候,pb已經先被刪除了,那麼後面的new就會為空,這是未知的計算。
異常安全:
Widget& Widget::operator=(const Widget& rhs){ if (this == &rhs) return *this; delete pb; //stop using current bitmap pb = new Bitmap(*rhs.pb); // start using a copy of rhs's bitmap return *this; // see Item 10 }
這個自賦值安全,但是沒有異常安全,如果new處出現了異常,那麼pb仍舊指向空。
2.解決辦法
通過調整語句順序:
Widget& Widget::operator=(const Widget& rhs){ Bitmap *pOrig = pb; // remember original pbpb = new Bitmap(*rhs.pb); // make pb point to a copy of *pb delete pOrig; // delete the original pb return *this; }
通過一箇中間變數來實現,而沒有使用if的判斷,因為可能會影響效率。
其實也可以這樣:
HasPtr & operator=(const HasPtr& hp){ std::string * t=new std::string(*hp.ps); delete ps; ps=t; i=hp.i; return *this; }
主要就是申請一個臨時變數來指向原來的空間或者是新申請的空間。//delete應該是不會出現異常的吧。
通過swap,賦值和交換
Widget& Widget::operator=(Widget rhs){ swap(rhs); // swap *this's data with return *this; // the copy's }
注意引數為值拷貝,在cpp459頁有講解,
總結:
- 判斷兩個地址是否相同
- 仔細地排列語句順序
- Copy and Swap
自賦值存在的知識點差不多這些。