当前位置: 首页 > news >正文

Effective C++读书笔记——item11(自赋值)

自赋值相关问题

  1. 自赋值情况示例
    • 明显的自赋值如w = w,还有不太容易辨别的情况,像a[i] = a[j](当ij值相同)、*px = *py(当pxpy指向同一对象)等,这些是由别名(有多种引用对象的方式)造成的,尤其在涉及引用、指针操作同类型多个对象以及继承体系中基类和派生类对象引用、指针转换时要考虑自赋值可能。
  2. 自赋值在资源管理类中的隐患
    • Widget类持有指向动态分配位图的裸指针pb为例,若operator=实现时未考虑自赋值情况,像最初不安全的实现:先delete pbnew Bitmap(*rhs.pb),当*thisrhs是同一个对象时,会导致删除了不该删除的资源(同时破坏了rhs的资源),最终使对象持有指向已删除对象的 “有毒” 指针。
    • Widget&
      Widget::operator=(const Widget& rhs)              // unsafe impl. of operator=
      {delete pb;                                      // stop using current bitmappb = new Bitmap(*rhs.pb);                       // start using a copy of rhs's bitmapreturn *this;                                   // see Item 10
      }
  3. 传统防止自赋值错误的方法及局限
    • 传统方法是在operator=开始处通过if (this == &rhs) return *this;进行一致性检测,若为自赋值则直接返回。但此方法只解决了自赋值安全问题,对于之前提到的operator=版本,其还存在异常不安全的问题,例如new Bitmap表达式引发异常时,会导致对象持有指向已删除位图的指针,后续无法安全处理。

兼顾异常安全与自赋值安全的方法

  1. 调整语句顺序
    • 通过先保存原指针指向的数据(如Bitmap *pOrig = pb;),再进行新数据的拷贝(pb = new Bitmap(*rhs.pb);),最后删除原数据(delete pOrig;)的语句顺序调整,能在保证异常安全的同时处理自赋值情况,即使new Bitmap抛出异常,对象原有状态也不会被破坏,且无需一致性检测,但可能不是最有效率的做法。
      ​
      Widget& Widget::operator=(const Widget& rhs)
      {Bitmap *pOrig = pb;               // remember original pbpb = new Bitmap(*rhs.pb);         // make pb point to a copy of *pbdelete pOrig;                     // delete the original pbreturn *this;
      }​

  2. 使用 “copy and swap” 技术
    • 涉及类中定义swap函数交换数据,一种实现是先创建参数对象的副本(Widget temp(rhs);),再通过swap(temp)交换*this和副本的数据;另一种变种是将operator=参数以传值方式接收(Widget& Widget::operator=(Widget rhs)),函数内直接swap(rhs)交换数据,后者在一定程度上可能让编译器产生更有效率的代码,但清晰度可能稍受影响。
    • class Widget {...void swap(Widget& rhs);       // exchange *this's and rhs's data;...                           // see Item 29 for details
      };Widget& Widget::operator=(const Widget& rhs)
      {Widget temp(rhs);             // make a copy of rhs's dataswap(temp);                   // swap *this's data with the copy'sreturn *this;
      }Widget& Widget::operator=(Widget rhs)   // rhs is a copy of the object
      {                                       // passed in — note pass by valswap(rhs);                            // swap *this's data with// the copy'sreturn *this;
      }

总结与注意事项

在编写代码时要确保operator=等操作多个对象的函数在对象自赋值或对象相同时行为良好,处理自赋值问题的技巧包括比较源和目标对象地址、关注语句顺序、使用 “copy and swap” 等方法,并且要根据实际情况权衡效率、代码清晰度等因素来选择合适的方式。


http://www.mrgr.cn/news/82918.html

相关文章:

  • RabbitMQ介绍以及基本使用
  • 计算机网络-SSH基本原理
  • RabbitMQ 从入门到精通:从工作模式到集群部署实战(二)
  • 计算分数加减表达式的值(信息学奥赛一本通-1079)
  • Elasticsearch:向量搜索的快速介绍
  • arm 下 多线程访问同一变量 ,使用原子操作 性能差问题
  • 来说数据库
  • C++ Qt练习项目 QChar功能测试
  • 尚硅谷· vue3+ts 知识点学习整理 |14h的课程(持续更ing)
  • aardio —— 虚表 —— 模拟属性框
  • 安卓OCR使用(Google ML Kit)
  • 【华为OD机试E卷C卷D卷】跳马【C++/Java/Python】
  • Python应用指南:高德交通态势数据(一)
  • java 核心知识点——基础知识
  • 群论学习笔记
  • 关于大一上的总结
  • 【Linux】sed编辑器
  • Functions
  • 高效工作流:用Mermaid绘制你的专属流程图;如何在Vue3中导入mermaid绘制流程图
  • SQL编程语言
  • Postman接口测试05|实战项目笔记
  • 进程件通信——网络通信——TCP
  • unity-入门查漏补缺0.2.03.10
  • 计算机网络学习
  • 【算法】算法初步
  • 在ComfyUI的python_embeded下编译安装module