这是我在阅读Effective c++中认为比较重要的部分,下面给出了我对这一节的理解,并写出对应的比较容易理解的代码。
有一份自我赋值不安全和异常不安全的代码如下:
class Bitmap {
};
class Widget {
private:
Widget(Bitmap*pb):p(pb){ }
Bitmap* p; //指向一个从heap分配而得的对象。
Widget& operator = (const Widget&rhs);
};
Widget& Widget::operator=(const Widget&rhs) {
delete p;
p = new Bitmap(*(rhs.p));
return *this;
}
当自我赋值时,delete删除了自身对象,最终发现自己持有一个指针指向一个已被删除的对象。
自我赋值安全,但不是异常安全的版本,加上
if (this == &rhs) return *this;
如果new Bitmap导致异常,不论是因为分配时内存不足或因为Bitmap的拷贝构造函数抛出异常,widget最终都会持有一个指针指向一块被删除的bitmap(针对上面的例子)
异常安全+自我赋值安全版本
Widget& Widget::operator=(const Widget&rhs) {
Bitmap*temp = p; //记住原先的p
p = new Bitmap(*rhs.p);//产生新的p
delete temp;//删除原来的
return *this;
}
如果new抛出异常,p保持现状,也能处理自我赋值。
请记住
确保当对象自我赋值时operator = 有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap.
确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。
扫描二维码关注公众号,回复: 2279711 查看本文章