您的位置:首页 > 编程语言 > C语言/C++

Effective C++ Item 11-在operator = 中处理"自我赋值"

2016-08-09 11:38 501 查看
Item 11-在operator = 中处理"自我赋值"(Handle assignment to self in operator = )

"自我赋值"发生在对象被赋值个自己:

Ex1:

class Widget{...};
Widget w;
...
w=w; //赋值给自己
Ex2:建立一个class用来保存一个指针指向一块动态分配的位图(bitmap)
class Bitmap{...};
class Widget
{
...;
private:
Bitmap* pb; //指针,指向一个从heap分配而得的对象
};

下面是实现operator = 实现代码,但自我赋值出现时并不安全
Widget &
Widget::operator = (const Widget& rhs) //一份不安全的operator = 实现版本
{
delete pb;
pb = new Bitmap(* rhs.pb) //使用rhs’s bitmap的副本
return *this;
}

如果operator = 函数内的*this和rhs是同一个对象,那么delete就不只是销毁当前对象的bitmap。它也销毁rhs和bitmap,return就会指向一个被删除的对象。

解决方案

1、operator = 最前面的一个"证同测试"(identity test)

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

2、复制一份再删除
Widget& Widget::operator = (const Widget& rhs)
{
Bitmap* pOrig = pb; //记住原先的pb
pb = new Bitmap(*rhs.pb); //令pb指向*pb的一个复件
delete pOrig; //删除原先的pb
return *this;
}

3、确保代码不但"异常安全"而且"自我赋值安全",copy and swap技术
class Widget
{
...
void swap(Widget& rhs); //交换*this的rhs的数据
};
Widget& Widget::operator = (const Widget& rhs)
{
Widget temp(rhs); //为rhs数据制作一份复件
swap(temp); //将*this数据和上述复件的数据交换
return *this;
}
请记住:
确保当对象自我赋值时operator = 有良好行为。其中技术包括比较"来源对象"和"目标对象"的地址,精心周到的语句顺序,以及copy and swap。

确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Effective C++