条款11:在operator=中处理“自我赋值”
什么是自我赋值,就是 v = v 这种类型的语句,也许很多人都会说鄙视这种写法,但是如下的写法会不会出现呢?
比如:a[i] = a[j]; // 不巧的是i可能和j相等
*px = *py; // 也许px和py刚好指向同一个对象呢
上述例子都是隐含的自我赋值。
再举一例:
class Bitmap // 位图类
{
...
}; class Widget
{
public:
Widget& operator=(const Widget& rhs); private:
Bitmap* pb; // 指向动态分配的位图对象
}; Widget& Widget::operator=(const Widget& rhs)
{
delete pb; // 释放当前位图对象
pb = new Bitmap(*rhs.pb); // 使用rhs中位图的副本
return *this;
}
现在假设*this和rhs是同一个对象呢?那么delete的调用就会释放*this的位图,其实同时也释放了rhs的位图资源,那么此时=的意义就变成了:让一个指针指向一个已被删除的对象,太可怕了。还好如下做法可以解决这个错误,被称为identity test:
Widget& Widget::operator=(const Widget& rhs)
{
if(this == &rhs) // identity test
return *this; // 如果是同一个对象则返回即可
else
{
delete pb; // 释放当前位图对象
pb = new Bitmap(*rhs.pb); // 使用rhs中位图的副本
return *this;
}
}
一个更好的赋值方案是使用copy and swap技术,如下所示:
class Widget
{
...
void swap(Widget& rhs); // 交换*this和rhs的内容
...
}; Widget& Widget::operator=(const Widget& rhs)
{
Widget temp(rhs); // 制作一个rhs的副本
swap(temp); // 将该副本内容和*this交换
return *this;
}
条款11:在operator=中处理“自我赋值”的更多相关文章
- EC读书笔记系列之6:条款11 在operator=中处理自我赋值
记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...
- Effective C++ -----条款11: 在operator=中处理“自我赋值”
确保当对象自我赋值时operator=有良好行为.其中技术包括比较“来源 对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap. 确定任何函数如果操作一个以上的对象,而其中多 ...
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to sel ...
- 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; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...
- Effective C++ 条款11:在operator=中处理"自我赋值"
"自我赋值"发生在对象被赋值给自己时: class Widget { ... }; Widget w; ... w = w; // 赋值给自己 a[i] = a[j]; // 潜在 ...
- 【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. ...
随机推荐
- yiStack平台维护
<一.> yiStack 二次封装 Iso通用发行版相关配置属性值替换1.1.yiStack AIO一体机环境根据部署子网替换修改示例如下:主要修改替换isolinux/ks-aio.cf ...
- markdown语法学习效果预览
注: 结合markdown官方文档 其中大部分例子和说明文字都摘自官方文档 官方链接:Markdown: Basics (快速入门). 一 段落.标题.区块代码 Markdown 支持两种标题的语法, ...
- 使用扩展方法(this 扩展类型)
namespace ConsoleApp_UseExtendWays{ class Program { static void Main(string[] args) { Student s = ne ...
- Loadrunner:场景中添加负载生成器
场景中添加负载生成器: (1)远程机子(假设ip为192.168.134.23)开启负载生成器 开始菜单找到:LoadRunner Agent Process 开启后任务栏会显示如下图: (2)场景中 ...
- C++ 牛人博客(不断更新中...)
http://www.zhangjiee.com/ 新浪微博@独酌逸醉. Github. GitCafe. stackoverflow. Quora http://cpp1x.org/ 刘未鹏 | M ...
- Hbase rest方式获取指定key范围内的值
代码如下: <?php class Monitor_Hbase{ private $rest_host = "http://10.99.90.39:8130/";//rest ...
- 1.5如何学习Linux驱动开发
1.准备一个自己熟悉的Linux操作系统,用于开发和测试Linux驱动,建议使用Ubuntu Linux 10.04及以上版本: 2.准备一块开发板,建议采用基于ARM11的开发板: 3.学习GUN ...
- 1.3查看Linux内核版本
1.目前Linux内核主要维护的三个版本:Linux2.4.Linux2.6和Linux3.x,Android使用的是Linux2.6:Linux3.x是最新推出的Linux内核版本: 2.查看Lin ...
- u-boot-1.1.6移植之dm9000
网卡dm9000的执行过程(u-boot版本:u-boot-1.1.6): 在board.c里面有eth_initialize(gd->bd); eth_initialize的实现在eth.c里 ...
- 软件工程 speedsnail 冲刺9
20150313 完成任务:为周五检查做了相关准备,包括稳定性测试,分辨率测试: 遇到问题: 问题1 进入关卡的开始蜗牛会跳一段距离 解决1 没有解决 明日任务: 冲刺结束