1. 程式人生 > >effective c++ (四)

effective c++ (四)

ret 內存不足 賦值 指向 enc 工作 cti sig 操作符

條款10:令operator=返回一個reference to *this

為了實現“連鎖賦值”,賦值操作符必須返回一個reference指向操作符的左側實參,這是你為classes實現賦值操作符時應該遵循的協議。

class Widget{
public:
      ...
      Widget& operator+=(const Widget& rhs)   //同樣適用於-=, *=
      {
              ...
              return *this;
      }

      Widget& operator=(const
Widget& rhs) //同樣適用於-=, *= { ... return *this; } Widget& operator=(int rhs) //此函數也是和,即使此一操作符參數類型不符合協定 { ... return *this; } };

註意,這只是一個協議,並無強制性。如不遵循它,代碼一樣可以通過編譯。然而這份協議被所有內置類型和標準程序庫提供的類型工作遵守(string vector complex tr1::shared_ptr)

請記住:

  • 令賦值操作符(assignment)操作符返回一個reference to *this

條款11:在operator=中處理“自我賦值”

1、一般而言,如果某段代碼操作pointers或references而它們被用來“指向多個相同類型”,就需要考慮這些對象是否為同一個。實際上,兩個對象只要來自同一個繼承體系,甚至不需要聲明為相同類型就可能造成“別名”(應為base class的指針或引用可以指向一個derived)。如:

a[i] = a[j] //若i與j具有相同的值,這便是自我賦值;

*px = *py//如果px與py恰巧指向同一個對象,則時自我賦值

void doSomething(const Base& rb, Derived* pd);//若rb與rp可能指向同一個對象

2、如果遵循條款13和14的忠告,你會運用對象來管理資源,而且你可以確定所謂“資源管理對象”在copy發生時有正確的舉措。在這種情況下你的賦值操作符或許是“自我賦值安全的”(self-assignment-safe),不需要額外操心

3、如下代碼,在自我賦值時會會拋出異常

class Bitmap { ... };
class Widget 
{
      ...
private:
   Bitmap* pb;  
};

Widget& Widget::Operator=(const Widget& rhs)
{
    delete pb;
    pb = new Bitmap(*rhs.pb);
   return *this;       
}

這裏若是自我復制問題是,operator=函數內的*this和rhs有可能是同一對象;若是如此delete就不只是銷毀當前對象的bitmap,也銷毀了rhs的bitmap

Widget& Widget::operator=(const Widget& rhs)
{
     if(this == &rhs) return *this;
     delete pb;
     pb = new Bitmap(*rhs.pb);
     return *this; 
}

如此在賦值前進行一個“認同測試(identify test)”達到自我賦值的檢驗目的

但是此段代碼不具備“異常安全性”,在new Bitmap導致異常(不論是因為分配時內存不足或因為Bitmap的copy構造函數拋出異常),Widget最終會持有一個指針指向一塊被刪除的Bitmap。

effective c++ (四)