effect C++operatro=で「自己付与」を処理

1878 ワード

自己代入
自己付与は、オブジェクトが自己に付与されたときに発生します.
class Widght{...}
Widget w;
...
w=w;   //     

付与動作は必ずしも一目で認識できるわけではない.
a[i]=a[j];   //  i j     
*px=*py;     //  px py         

リソースを自分で管理しようとすると、「使用を停止する前に意外に罠を解放した」と落ちる可能性があります.
ポインタが指す動的割り当てのビットマップを保存するためにclassを作成するとします.
class Bitmap{...}
class Widget{
 ...
private:
  Bitmap *pb;//     heap       
}
Widget&Widget::operator=(const Widget& rhs) //    operator=
{
    delete pb;
    pb=new Bitmap(*rhs.pb);
    return *this;
}

operator=関数内の*thisとrhsは同じオブジェクトである可能性があります.これによりdeleteは現在のbitmapを破棄するだけでなくrhsのbitmapも破棄する.
従来の方法は、「証明書とテスト」を追加することです.
Widget&Widget::operator=(const Widget& rhs) //    operator=
{
    if(this==&rhs)return *this;
    delete pb;
    pb=new Bitmap(*rhs.pb);
    return *this;
}

しかし、「new Bitmap」が異常(割り当て時のメモリ不足やBitmapのcopyコンストラクタによる異常放出にかかわらず)を引き起こすと、Widgetは最終的に削除するBitmapを指すポインタを持つ.
以下のコードは、pbが指すものをコピーする前にpbを削除しないように注意する必要があります.
Widget&Widget::operator=(const Widget& rhs) 
{
     Bitmap* pOrig =pb;			//     pb
     pb=new Bitmap(*rhs.pb);		//  pb  *pb     
    delete pOrig;			//     pb
     return *this;
}

現在、「newBitmap」が異常を放出した場合、pbは元のままになります.
copy and swapもご利用いただけます
class Bitmap{...}
class Widget{
 ...
 void swap (Widget& rhs);	//  *this   rhs    
 ...
}
Widget&Widget::operator=(const Widget& rhs) 
{
    Widget temp(rhs);		// rhs        
    swap(temp);                 // *this            
     return *this;
}

オブジェクトが自己割り当てされているときにoperator=が良好に動作していることを確認します.テクノロジーには、「ソース・オブジェクト」と「ターゲット・オブジェクト」のアドレスの比較、周到な文の順序、copy-and-swapが含まれます.
任意の関数が1つ以上のオブジェクトを操作し、複数のオブジェクトが同じオブジェクトである場合でも、その動作が正しいことを確認します.