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

本文探讨了自我赋值的危害及其对程序稳定性的影响,并提供了一种改进的赋值运算符实现方法,确保即使在异常情况下也能保持原有状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

防止自我赋值很有必要

Widget w;
w = w;
a[i] = a[j]; //a[i]和a[j]实际上指向同一个元素
*pi = *pj; //pi和pj实际上指向同一个元素

自我赋值的危害

Widget
{
private:
    Test *p;
};
Widget &Widget::operator=(const Widget &w)
{
  delete p;
  p = new int (*w.p);
  return *this;
}

如果是自我赋值,会把自己的空间释放掉,即当执行delete p后,w.p已经指向一个被释放的内存空间(此时*w.p的内容未知);当执行 p = new int(*w.p);即让p重新指向一个存储了(*w.p)的内存空间,该内存空间内容又是未知的。当再次引用时,会出现未定义的行为。

改良版本

Widget &Widget::operator=(const Widget &w)
{
  if (this == &w)
  {
      return *this;
  }
  delete p;
  p = new Test(*w.p);
  return *this;
};

这个类虽然能避免自我赋值的问题,但是,如果new Test时抛出异常,那么Widget最终会持有一个指针指向一块被删除的内存区域,这样的指针是有害的。

改成这样

Widget &Widget::operator=(const Widget &rhs)
{
  Test *porg = p;
  p = new Test(*rhs.p);
  delete porg;
  return *this;
}

此时new Test发生异常,那么p可以保持原状。(异常发生的时候,不会给p赋值)

delete prog;保证了p原来指向的内存空间也会被顺利释放。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值