声明:
- 文中内容收集整理自《Effective C++(中文版)第三版》,版权归原书所有。
- 本内容在作者现有能力的基础上有所删减,另加入部分作者自己的理解,有纰漏之处敬请指正。
条款10:令operator=返回一个reference to *this
Have assignment operators return a feference to *this.
请记住:
令赋值(assignment)运算符返回一个reference to *this。
条款11:在operator=处理“自我赋值”
Handle assignment to self in operator=.
“自我赋值”发生在对象被赋值给自己时。
class Widget{...}
Widget w;
...
w = w; //赋值给自己
//潜在的自我赋值
a[i] = a[j];
*px = *py;
要阻止自我赋值,传统的做法是在operator=最前面加一个“证同测试”达到“自我赋值”的检验目的:
class Bitmap{...}
class Widget
{
...
private:
Bitmap* pb;
}
Widget& Widget::operator=(const Widget& rhs)
{
if(this == &rhs) return this;
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
但以上代码仍不具备“异常安全性”,如果new Bitmap导致异常,Widget最终会持有一个指针指向一块被删除的Bitmap。
令人高兴的是,让operator=具备“异常安全性”,往往自动获得“自我赋值安全”回报。把焦点放在实现“异常安全性”上,注意在复制pb所指的东西之前别删除pb。
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap *pOrig = pb;
//delete pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
现在如果new Bitmap抛出异常,pb能够保持原状。而且还能够处理自赋值。
当然,还有更好的替代方案,那就是“copy and swap技术”。
class Bitmap{...}
class Widget
{
...
void swap(Widget& rhs); //交换*this和rhs的数据
...
private:
Bitmap* pb;
}
Widget& Widget::operator=(Widget rhs)
{
//by value传递参数,rhs为局部变量,函数结束后自动调用析构函数销毁
swap(rhs);
return *this;
}
请记住:
确保当对象自我赋值时operator=有良好的行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy_and_swap。
确定任何函数如果操作一个以上的对象,而且其中多个对象是同一对象时,其行为仍然正确。