笔记:条款11: 在operator= 中处理“自我赋值”

这是我在阅读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.

确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

猜你喜欢

转载自blog.csdn.net/lkq_primer/article/details/81121787