为什么重载操作符=使异常安全



非常直接的问题。

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

重载拷贝赋值时,书(Effective c++)中说:以下代码是异常安全的。

Widget& Widget::operator=(const Widget& rhs) {
    if (rhs == *this) return;
    Bitmap* pOrig = pb; //?? why remember the pb can do exception safety?
    pb = new Bitmap(*rhs.pb);
    delete pOrig;
    return *this;
  }

书中说:即使通过新的位图(*rhs.pb)遇到异常,上面的代码能做到异常安全,pb能保持不变,指针不指向NULL吗?但是怎么做,为什么?有人能帮我吗?谢谢!

虽然这个问题可能不太精确,但我认为我仍然明白了要点:

想象一下,代码应该写成如下:

Widget& Widget::operator=(const Widget& rhs)
{
    if (rhs == *this) // actually, you'd rather do &rhs == this!
                      // you don't want self-assignment
        return;
    delete pb;
    pb = new Bitmap(*rhs.pb);
    return *this;
}

会发生什么,如果new Bitamp()异常失败-那么pb已经被删除-并指向无效内存!

首先记住pb的值,如果创建异常失败,则没有修改this,即使发生异常,它仍然有效

如果在new Bitmap(*rhs.pb)的构造过程中抛出异常,则Widget的状态仍然保持不变。

如果在做new Bitmap(*rhs.pb)之前先删除pb:

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

new Bitmap(*rhs.pb)失败(抛出异常),在Widget中没有Bitmap实例,pb指向Bitmap的删除实例。这将在销毁Widget时崩溃

最新更新