您的位置:首页 > 其它

重载赋值运算符中需要注意的两个问题

2014-08-30 15:24 197 查看
前言

  如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符。

  然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符。

第一点:请返回 reference to *this

  我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用。

  因此,在重载运算符函数末尾请写上如这样的语句 return *this;

  除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做。

第二点:处理好自我赋值

  首先,我们看一段问题代码:

// 位图资源类
class Bitmap { /*......*/ };

// 位图资源管理类
class Widget {
public:
//......
Widget & operator=(const Widget & rhs);
//......
private:
//......
Bitmap *pb;    // 位图资源。指针类型,指向 heap 分配而得的空间
//......
};

Widget & Widget::operator=(const Widget & rhs)
{
delete pb;    // 删除原有资源
pb = new Bitmap(*rhs.pb);    // 申请新的资源并存放右操作数的数据
return *this;
}


  问题出在重载函数中,如果左右操作数是相同的对象,delete 掉原有资源之后,所有数据信息就全丢了。

  因此,运算符重载函数需要加上一个证同测试:

Widget & Widget::operator=(const Widget & rhs)
{
// 加入证同测试
if (this == &rhs)
return *this;

delete pb;    // 删除原有资源
pb = new Bitmap(*rhs.pb);    // 申请新的资源

return *this;
}


  但这依然不是最好的做法:因为 new 有可能失败,导致资源丢失。

  下面这个精心设计的重载函数才是我们需要的:

Widget & Widget::operator=(const Widget & rhs)
{
Bitmap * pOrig = pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;

return *this;
}


  这个实现就保证了赋值的安全,健壮,是个非常可取的方案。

小结

  赋值运算符还有一些其他的非常可取的实现,这里就不一一讲解了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: