11 在operator中处理自我赋值

一、有哪些不明显的自我赋值?

  • a[i] = a[j]; //潜在的自我赋值
  • *px = * py;
  • base class 和derived class
class Base{...};
class Derived :public Base{...};
void doSomething(const Base& rb,Derived* pd);

二、自我赋值存在的问题

  • 可能会在停止使用之前意外释放掉
class Bitmap{...};
class Widget{
...
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs){
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

三、如何解决

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

这种方式仍然存在异常安全方面的问题。如果new Bitmap抛出异常,Widget 最终会持有一个指针指向一块被删除的Bitmap。

  • 使之具有异常安全性
Widget& Widget::operator=(const Widget& rhs){
    Bitmap* pOrig = pb;
    pb = new Bitmap(*rhs.pb);
    delete pOrig;
    return *this;
}

这种方式可以解决自我赋值的问题。通过将pb备份,再将*(rhs.pb)复制到pb,接着再删除pb。不会因为,rhs.pb和this->pb相同而导致先释放掉pb的问题。若new Bitmap抛出异常,pb的也指向不会改变。效率虽然不高,但是方法可行。

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

该方式的另一种变体。该种写法将copying动作从函数本体转移至函数参数构造阶段,可令编译器又是生成更高效的代码。

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

四、总结

  • 确保当对象自我赋值时operator=有良好的行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap。
  • 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值