Effective C++ 条款11:在operator=中处理"自我赋值"
”自我赋值”发生在对象被赋值给自己时:
class Widget { ... };
Widget w;
...
w = w; // 赋值给自己
a[i] = a[j]; // 潜在的自我赋值
*px = *py; // 潜在的自我赋值
class Base { ... };
class Derived: public Base { ... };
void doSomething(const Base& rb, Derived* pd); // rb和*pd有可能其实是同一对象
尝试自我管理资源
class Bitmap { ... };
class Widget {
...
private:
Bitmap* pb; // 指针,指向一个从heap分配而得的对象
};
// 一个不安全的operator=实现版本
Widget& Widget::operator=(const Widget& rhs) {
delete pb; // 停止使用当前的bitmap
pb = new Bitmap(*rhs.pb); // 使用rhs's bitmap的副本
return *this; // 见条款10
}
可能出现的问题就是,*this和rhs可能是同一个对象,最后会导致自己持有一个指针指向一个已被删除的对象!
自我安全性
Widget& Widget::operator=(const Widget& rhs) {
if (this == rhs) return *this; // 证同测试
// 如果是自我赋值,就不做任何事情
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
以上代码确实解决了自我赋值的问题,但是会引发异常的问题,如果new Bitmap导致异常了,那么Widget最终会持有一个指针指向一块被删除的Bitmap。
异常安全性
Widget& Widget::operator=(const Widget& rhs) {
Bitmap* pOrig = pb; // 记住原先的pb
pb = new Bitmap(*rhs.pb);
delete pOrig; // 删除原先的pb
return *this;
}
copy and swap
class Widget {
...
void swap(Widget& rhs);
...
};
Widget& Widget::operator=(const Widget& rhs) {
Widget temp(rhs);
swap(temp);
return *this;
}
Widget& Widget::operator=(Widget rhs) { // 注意这里是传值
swap(rhs);
return *this;
}
总结
- 确保当对象自我赋值时operator=有良好行为。其中技术包括比较”来源对象”和”目标对象”的地址、精心周到的语句顺序、以及copy-and-swap.
- 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。
Effective C++ 条款11:在operator=中处理"自我赋值"的更多相关文章
- Effective C++ -----条款11: 在operator=中处理“自我赋值”
确保当对象自我赋值时operator=有良好行为.其中技术包括比较“来源 对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap. 确定任何函数如果操作一个以上的对象,而其中多 ...
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to sel ...
- EC读书笔记系列之6:条款11 在operator=中处理自我赋值
记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...
- Effective C++_笔记_条款11_在operator=中处理“自我赋值”
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为什么会出现自我赋值呢?不明显的自我赋值,是“别名”带来的结果: ...
- 11——在operator=中处理自我赋值
在operator=函数中加一个测试: if(&rhs==this) copy and swap
- Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分
1.潜在的自我赋值 a[i] = a[j]; *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...
- 条款11:在operator=中处理“自我赋值”
什么是自我赋值,就是 v = v 这种类型的语句,也许很多人都会说鄙视这种写法,但是如下的写法会不会出现呢? 比如:a[i] = a[j]; // 不巧的是i可能和j相等 *px = *py ...
- 【11】在operator=中处理“自我赋值”
1.自我赋值,看起来愚蠢,但是却合法.有些自我赋值一眼就可看出来.有些自我赋值是潜在的.比如:a[i] = a[j]; *px = *py; 甚至不同类型的指针,都指向同一个地址,也是自我赋值,这一类 ...
- [Effective C++ --011]在operator=中处理“自我赋值”
一.何谓“自我赋值”? 1.1.场合一 直接赋值 w = w; 1.2.场合二 同一数组 a[i] = a[j]: 1.3.场合三 指针 *px = *py: 1.4. ...
随机推荐
- nvm-windows 手动安装 nvm use 无效 'node' 不是内部或外部命令,也不是可运行的程序
按照这两位前辈的教程,安装了nvm-windows. http://www.cnblogs.com/yesyes/p/7403184.html http://blog.csdn.net/jingsi1 ...
- JS给html控件赋值
<html> <head> <title> JS给html控件赋值 </title> <script language="javascr ...
- 四、H5 录制视频 Web Real-Time Communication
Web Real-Time Communication HTML5实现视频直播功能思路详解_html5教程技巧_脚本之家 https://m.jb51.net/html5/587215.html
- 创建使用pycharm virtualenv
创建使用pycharm virtualenv 在python的世界里,真该感谢有PyCharm,pip,virtualenv 这些好东东,为python程序员提供了极大的方便. virtualenv ...
- 利用jdt快速实现pmd的功能
jdt可以做语法树分析,并且支持visitor模式对代码进行分析.跟pmd的分析方式一样,我们只要实现 visitor接口即可实现一个插件. @Service("requestMapping ...
- Python元组组成的列表转化为字典
虽然元组.列表不可以直接转化为字典,但下面的确是可行的,因为经常用python从数据库中读出的是元组形式的数据. # 原始数据 rows = (('apollo', 'male', '164.jpeg ...
- 我的Android进阶之旅------>Java文件大小转换工具类 (B,KB,MB,GB,TB,PB之间的大小转换)
Java文件大小转换工具类 (B,KB,MB,GB,TB,PB之间的大小转换) 有时候要做出如下所示的展示文件大小的效果时候,需要对文件大小进行转换,然后再进行相关的代码逻辑编写. 下面是一个Java ...
- window下安装php的imagick和imagemagick扩展教程
最近的PHP项目中,需要用到切图和缩图的效果,在linux测试服务器上很轻松的就安装好php imagick扩展.但是在本地windows开发环境,安装过程遇到好多问题,在此与大家分享. 1. 下载 ...
- laravel queue队列使用
一篇文章: laravel中的队列服务跟其他队列服务也没有什么不同,都是最符合人类思维的最简单最普遍的流程:有一个地方存放队列信息,一个PHP进程在运行时将任务写入,另外一个PHP守护进程轮询队列信息 ...
- Codeforces Round #475 (Div. 2)
B. Messages 题意:有n个消息分别在ti的时候收到.设所有消息收到时初始值为A,每过一秒,其值减去B.当在某一秒选择读某个消息时,获值为当前消息的值:如果在某一秒结束的时候,手上有k则消息未 ...