Effective C++(11) 自我赋值(a=a)时会发生什么?
自我赋值看似有点愚蠢的行为,其实总会发生的首先:它是合法的,其次,它不一定是安全的,再次,它有时候不是那么明显。
先看一个Demo
class Widget { ... };
Widget w;
...
/** 最明显的自我赋值 **/
w = w;
/** 不那么明显的自我赋值 **/
// 在某个地方实现了i = j或者相同作用的事情
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* pd;
};
/** operator=的代码实现 **/
Widget&
Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
若rhs和当前对象是同一对象,那么在销毁当前对象的pb时,把rhs的对象也销毁了。
改进:认同测试
/** operator=的代码实现 **/
Widget&
Widget::operator=(const Widget& rhs)
{
if (this == &rhs) return *this; // 认同测试 delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
如果new Bitmap()发生异常,那么结果就是pb赋值直白,Widget最终持有一个指针指向一块被删除的Bitmap。
改进一:精心安排语句
/** operator=的代码实现 **/
Widget&
Widget::operator=(const Widget& rhs)
{
Bitmap* pOrig = pb;
pb = new Bitmap(*rhs.pb); // 如果new Bitmap抛出异常,pb保持原状
delete pOrig;
return *this;
}
class Widget {
...
void swap(Widget& rhs);
...
};
Widget& Widget::operator=(const Wdiget& rhs)
{
Widget temp(rhs);
swap(temp);
return *this;
}
思想:
拷贝构造函数要声明为“按值传递”按值传递会造成一份副本
确保当对象自我赋值时operator=有良好的行为。
包括:
对象来源目标对象地址
语句顺序
确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。
Effective C++(11) 自我赋值(a=a)时会发生什么?的更多相关文章
- 读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to sel ...
- Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分
1.潜在的自我赋值 a[i] = a[j]; *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...
- Effective C++ -----条款11: 在operator=中处理“自我赋值”
确保当对象自我赋值时operator=有良好行为.其中技术包括比较“来源 对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap. 确定任何函数如果操作一个以上的对象,而其中多 ...
- Effective C++ 条款11:在operator=中处理"自我赋值"
"自我赋值"发生在对象被赋值给自己时: class Widget { ... }; Widget w; ... w = w; // 赋值给自己 a[i] = a[j]; // 潜在 ...
- Effective C++_笔记_条款11_在operator=中处理“自我赋值”
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为什么会出现自我赋值呢?不明显的自我赋值,是“别名”带来的结果: ...
- 条款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. ...
- EC读书笔记系列之6:条款11 在operator=中处理自我赋值
记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...
随机推荐
- OCP读书笔记(26) - 题库(ExamF)
501.Note the output of the following query;SQL> SELECT flashback_archieve_name, status FROM dba_f ...
- MySQL中游标使用以及读取文本数据
原文:MySQL中游标使用以及读取文本数据 前言 之前一直没有接触数据库的学习,只是本科时候修了一本数据库基本知识的课.当时只对C++感兴趣,天真的认为其它的课都没有用,数据库也是半懂不懂,胡乱就考试 ...
- android控制文件:ViewPager+Fragment+GridView使用(与AndroidQuery框架结合)
最近我看到一个AndroidQuery该框架.里面Demo,有一个屏幕,让博主喜欢.很顺利的左右滑动,感觉非常好,所以拿来和大家分享一下.看看结果图.: 从图中能够看出.上面的布局是一个Layout里 ...
- IronPython和C#交互
IronPython和C#交互 IronPython是一个.NET平台上的Python实现,包括了完整的编译器.执行引擎与运行时支持,能够与.NET已有的库无缝整合到一起. IronPython已经很 ...
- Tomcat剖析(三):连接器(2)
Tomcat剖析(三):连接器(2) 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器(1) 4 ...
- 【百度地图API】如何给自定义覆盖物添加事件
原文:[百度地图API]如何给自定义覆盖物添加事件 摘要: 给marker.lable.circle等Overlay添加事件很简单,直接addEventListener即可.那么,自定义覆盖物的事件应 ...
- Swift语言指南(八)--语言基础之元组
原文:Swift语言指南(八)--语言基础之元组 元组 元组(Tuples)将多个值组合为一个复合值.元组内的值可以是任何类型,各个元素不需要为相同类型(各个元素之间类型独立,互不干扰--Joe.Hu ...
- IOS启动其他应用程序
从app1打开app2.主要的思路就是,能够为app2定义一个URL,在app1中通过打开这个URL来打开app2,在此过程中.能够传送一些參数. 在app1的代码中打开刚才定义的URL.代码例如以下 ...
- POJ 1565 Skew Binary(简单的问题)
[简要题意]:第二个是数字系统的代表性的定义.而给了你这个号码系统提示的形式和十进制转换之间的关系.现在给你一些这样的系统.让你把它变成2二进制输出. [分析]:当中 base[k] = 2^(k ...
- T4模板生成不同部署环境下的配置文件
使用T4模板生成不同部署环境下的配置文件 在开发企业级应用的时候,通常会有不同的开发环境,比如有开发环境,测试环境,正式环境,生产环境等.在一份代码部署到不同环境的时候,不同环境的配置文件可能需要根据 ...