effective c++ 11 operator= 处理自我赋值

news/2024/10/30 16:14:12/

effective c++ 11 operator= 处理自我赋值

我们知道复制构造函数和赋值运算符的区别是赋值构造函数用于创建一个新的对象,而赋值运算符用于给一个已经存在的对象重新赋值。

因此赋值运算符就可能存在把自己赋值给自己的情况,本节就是专门讨论这个场景的。

分析

本文介绍了三种办法来处理这个问题,其实作者后续不仅仅讨论了自我赋值的问题,还讨论了赋值运算符的异常安全问题

第一种方法比较简单,既然operator=可能存在自我赋值的场景,那么我们便在进入赋值运算符的函数内部首先做一个"证同测试"。如果是同一个对象,就直接返回。

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

第二种方法其实并不是在讨论"证同测试"的方法。而是在讨论异常安全性。 个人认为Scott Mayer的书有这样的特点,它不像是一本教科书,而是像一本杂谈。 可能聊到某个话题的时候,可能也和另一个话题有关系,就也会谈一谈。

我们注意方法一中剩下拷贝的代码。如果new Bitmap出现异常,那么原来对象的pb指向的对象就已经被删除了。这是不能忍受的。后面在item-29中专门讨论异常安全性的时候会提到,异常安全性就类似于数据库的"回滚"机制,当操作失败时,需要恢复到执行之前的样子。显然上面的代码在这方面是有问题的。

	delete pb;pb = new Bitmap(*rhs.pb);

修改方法也很简单,即先将原来的pb指针保存起来。只有当new成功了之后,再删除原来的指针指向的对象。

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

第三种方法其实也是在讨论异常安全性,只不过在代码上更加简洁,其使用了copy-and-swap的思想。首先将Widget对象拷贝给对象temp,接着将temp和当前的对象进行交换。

Widget& Widget::operator=(const Widget& rhs)
{// Copy constructor: make copy of rhs data.Widget temp(rhs);swap(const_cast<Widget&>(rhs));return *this;
}

总结

  • 确保当对象自我赋值时operator=有良好行为。其中技术包括比较"来源对象"和"目标对象"的地址、精心周到的语句顺序,以及copy-and-swap。
  • 确定任何函数做过操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

http://www.ppmy.cn/news/78445.html

相关文章

MySQL(用户管理)

文章目录 1 用户1.1 用户信息1.2 创建用户1.3 删除用户1.4 修改用户密码 2 数据库的权限2.1 给用户授权2.2 回收权限 1 用户 1.1 用户信息 MySQL中的用户&#xff0c;都存储在系统数据库mysql的user表中 host&#xff1a; 表示这个用户可以从哪个主机登陆&#xff0c;如果是l…

日志收集机制和日志处理流程规范

本博客地址&#xff1a;https://security.blog.csdn.net/article/details/130792958 一、日志收集与处理流程 云原生平台中对日志提取收集以及分析处理的流程与传统日志处理模式大致是一样的&#xff0c;包括收集、ETL、索引、存储、检索、关联、可视化、分析、报告这9个步骤…

缓存被穿透了怎么办?

首先来了解几个概念&#xff1a; 缓存穿透&#xff1a;大量请求根本不存在的key 缓存雪崩&#xff1a;redis中大量key集体过期 缓存击穿&#xff1a;redis中一个热点key过期&#xff08;大量用户访问该热点key&#xff0c;但是热点key过期&#xff09; 穿透解决方案 对空值…

Ruby教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 Ruby&#xff0c;一种简单快捷的面向对象&#xff08;面向对象程序设计&#xff09;脚本语言&#xff0c;在20世纪90年代由日本人松本行弘(Yukihiro Matsumoto)开发&#xff0c;遵守GPL协议和Ruby License。它的灵感与特性来自于 Perl、Smalltalk、Eiffel、Ada以及 L…

离线安装python、pip和python的第三方库

1.安装python3 1.1下载python3 安装python3的网址为点击这里 选择想要下载的对应版本进行下载&#xff0c;这里使用的是63位的Windows系统&#xff0c;因此下载的选的是&#xff1a; 下载后如图&#xff1a; python-3.7.9-amd64.exe是python3的安装程序 1.2安装python3 1…

SQL学习日记

目录 一、数据定义&#xff08;create&#xff0c;alter&#xff0c;drop&#xff09; 1.1数据类型 补充注释 1.2定义基本表&#xff08;create&#xff0c;alter&#xff0c;drop&#xff09; 1.3约束 1.3.1主键约束 1.3.2外码约束 ​编辑 补充CASCADE 关键字 1.3.3…

Linux---文件操作命令(cp、mv、rm)

1. cp命令 cp命令可以用于复制文件\文件夹&#xff0c;cp命令来自英文单词&#xff1a;copy。 语法&#xff1a;cp [选项] 参数1 参数2 参数1&#xff1a;Linux路径&#xff0c;表示被复制的文件或文件夹 参数2&#xff1a;Linux路径&#xff0c;表示要复制去的地方 选…

辨析读写json文件常用json.loads()、json.load()和json.dumps()、json.dump()区别及ensure_ascii参数

目录 写在前面一、loads 和 load1.1 loads解释及代码实例1.2 load解释及代码实例 二、dumps 和 dump2.1 dumps解释及代码实例2.2 dump解释及代码实例2.3 ensure_ascii参数&#xff08;Ture or False&#xff09; 写在前面 一句话概括 json.loads 接受字符串 json.load 接受文…