在operator=中处理”自我赋值“

本文探讨了在C++中实现自我赋值操作符时可能遇到的问题及其解决方案,并介绍了如何确保异常安全性的几种方法。
原文链接:http://www.cnblogs.com/dwdxdy/archive/2012/07/17/2595821.html
 

首先通过一个例子引出自我赋值可能会导致的问题,例子如下:

  1. classBitmap{...};
  2. classWidget{
  3. public:
  4. ...
  5. Widget&operator=(constWidget& rhs);
  6. ...
  7. private:
  8. Bitmap* pb;
  9. };
  10. Widget&Widget::operator=(constWidget& rhs)//一份不安全的operator=实现版本
  11. {
  12. delete pb;
  13. pb =newBitmap(*rhs.pb);
  14. return*this;
  15. }

由于Widget类包含动态分配对象的指针,因而需要自定义拷贝构造函数和赋值符函数.

在上述operator=函数中,如果*this(赋值的目的端)和rhs是同一个对象,将会导致*this对象里的pb指针指向一个已被删除的对象.

通过在operator=中增加一个证同测试,可以阻止这种错误.代码实现如下:

  1. Widget&Widget::operator=(constWidget& rhs)
  2. {
  3. if(this==&rhs)//证同测试
  4. return*this;
  5. delete pb;
  6. pb =newBitmap(*rhs.pb);
  7. return*this;
  8. }

虽然增加证同测试后,可以达到自我赋值的安全性,但不具备异常安全性.

如果"new Bitmap"导致异常,Widget最终会持有一个指针指向一块被删除的Bitmap

这样的指针有害,我们无法安全地删除它们,甚至无法安全地读取它们.

通过合理安排语句,可以实现异常安全的代码.代码实现如下:

  1. Widget&Widget::operator=(constWidget& rhs)
  2. {
  3. Bitmap* pOrig = pb;
  4. pb =newBitmap(*rhs.pb);
  5. delete pOrig;
  6. return*this;
  7. }

如果"new Bitmap"抛出异常,pb会保持原状.

即使没有证测试,上述代码还是能够处理自我赋值.

此外,还有一种方法copy and swap技术可以实现operator=函数的异常安全和自我赋值安全.代码实现如下:

  1. Widget&Widget::operator=(constWidget& rhs)
  2. {
  3. Widget temp(rhs);//为rhs数据制作一份复件
  4. swap(temp);//将*this数据和上述复件的数据交换
  5. return*this;
  6. }

上述代码中,第3行代码创建临时变量temp,作为rhs数据的一份复件.

由于swap函数会交换*this和参数对象的数据,如果直接将rhs作为参数,则会改变rhs对象的值,与operator=的操作不符.

我们可以将operator=函数声明为"以by value方式接受实参",这样可减少临时变量temp的创建

将"copying动作"从函数本体移至"函数参数构造阶段".代码如下:

  1. Widget&Widget::operator=(Widget rhs)//pass by value,rhs是被传对象的一份复件
  2. {
  3. swap(this);//将*this的数据和复件的数据互换
  4. return*this;
  5. }
不过这个方法为了伶俐巧妙的修补牺牲了清晰性。





转载于:https://www.cnblogs.com/Lighters-c/p/6080680.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值