非常直接的问题。
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
时崩溃