effective c++ 条款11:在operator=中处理“自我赋值”

注意:
确保当对象自我赋值时operator=有良好行为。 

class Widget { ... };
Widget w;
...
w = w;  //赋值给自己

a[i] = a[j]; //潜在的自我赋值
*px = *py;   //潜在的自我赋值

class Base { ... };
class Derived: public Base { ... };
void doSomething(const Base& rb, Derived* pd);  //rb和*pd有可能是同一对象

 

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

Widget&
Widget::operator=(const Widget& rhs) //不安全的operator=实现版本
{
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

如果是自我赋值,那rhs.pb就已经被delete pb了。

解决方法:比较是否同一个对象

Widget& Widget::operator=(const Widget& rhs)
{
    if (this == &rhs) return *this; //identity test

    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

上面的代码还有个潜在问题,如果Bitmap出现异常了,但pb已经被delete了。

较好的一个方法:

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


另外一个方式是使用copy and swap

class Widget {
...
void swap(Widget& rhs);
...
};

Widget& Widget::operator=(const Widget& rhs)
{
    Widget temp(rhs);
    swap(temp);
    return *this;
}

 




posted @ 2018-06-15 13:23  pfsi  阅读(131)  评论(0编辑  收藏  举报