”自我赋值”发生在对象被赋值给自己时:

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;
}

总结

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

Effective C++ 条款11:在operator=中处理"自我赋值"的更多相关文章

  1. Effective C++ -----条款11: 在operator=中处理“自我赋值”

    确保当对象自我赋值时operator=有良好行为.其中技术包括比较“来源 对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap. 确定任何函数如果操作一个以上的对象,而其中多 ...

  2. 读书笔记 effective c++ Item 11 在operator=中处理自我赋值

    1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: class Widget { ... }; Widget w; ... w = w; // assignment to sel ...

  3. EC读书笔记系列之6:条款11 在operator=中处理自我赋值

    记住: ★确保当对象自我赋值时operator=有良好行为.有三种方法:比较“来源对象”和“目标对象”的地址.精心周到的语句顺序.以及copy-and-swap技术 ★确定任何函数若操作一个以上对象, ...

  4. Effective C++_笔记_条款11_在operator=中处理“自我赋值”

    (整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 为什么会出现自我赋值呢?不明显的自我赋值,是“别名”带来的结果: ...

  5. 11——在operator=中处理自我赋值

    在operator=函数中加一个测试: if(&rhs==this) copy and swap

  6. Effective C++ 条款11,12 在operator= 中处理“自我赋值” || 复制对象时不要忘记每一个成分

    1.潜在的自我赋值     a[i] = a[j];     *px = *py; 当两个对象来自同一个继承体系时,他们甚至不需要声明为相同类型就可能造成别名. 现在担心的问题是:假如指向同一个对象, ...

  7. 条款11:在operator=中处理“自我赋值”

    什么是自我赋值,就是 v = v 这种类型的语句,也许很多人都会说鄙视这种写法,但是如下的写法会不会出现呢? 比如:a[i] = a[j];      // 不巧的是i可能和j相等 *px = *py ...

  8. 【11】在operator=中处理“自我赋值”

    1.自我赋值,看起来愚蠢,但是却合法.有些自我赋值一眼就可看出来.有些自我赋值是潜在的.比如:a[i] = a[j]; *px = *py; 甚至不同类型的指针,都指向同一个地址,也是自我赋值,这一类 ...

  9. [Effective C++ --011]在operator=中处理“自我赋值”

    一.何谓“自我赋值”? 1.1.场合一 直接赋值 w = w; 1.2.场合二 同一数组         a[i] = a[j]: 1.3.场合三 指针         *px = *py: 1.4. ...

随机推荐

  1. Android获取 应用程序大小,数据大小,缓存大小

    在项目中创建,android.content.pm 包名.里面创建两个aidl文件.PackageStats.aidl  和 IPackageStatsObserver.aidl. PackageSt ...

  2. 《转》适用于开发人员的10个最佳ASP.NET的CMS系统

    1) mojoportal mojoPortal 是一个开源的.用 C# 编写的站点框架和内容管理系统,可以运行在 Windows 中的 ASP.NET 和 Linux/Mac OS X 中的 Mon ...

  3. Delphi TreeView – 自动展开树形结构

    Delphi TreeView – 自动展开树形结构 当处理完TreeView控件树形结构的数据后,需要默认自动全部展开,可以用到TreeView的Expanded属性. 1 2 3 4 5 6 7 ...

  4. 面试STAR法则

    昨天投了几家公司的简历,A公司还没看简历,B公司没有通过简历,另外的后说(其实只投了这两家),B公司最终给了蛮中肯的回复: 虽然,一开始看到这样的结果,有些失落,仔细看过回复后,有些不屑和好奇.百度了 ...

  5. 【BZOJ4547】Hdu5171 小奇的集合 矩阵乘法

    [BZOJ4547]Hdu5171 小奇的集合 Description 有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大值.(数据保证这 ...

  6. java代理与动态代理的学习

    静态代理比较简单,就是代理对象与被代理对象继承相同的接口,代理类负责调用被代理类(委托类)的对象的相关方法去提供具体的服务,一个代理类只能为一个接口服务,要是有很多服务的话需要开很多代理类.而动态代理 ...

  7. IO流入门-第十二章-ObjectInputStream_ObjectOutputStream

    DataInputStream和DataOutputStream基本用法和方法示例,序列化和反序列化 import java.io.Serializable; //该接口是一个“可序列化”的 ,没有任 ...

  8. 从es中拉取全部数据/大量数据 使用scroll+scan避免深分页

    es一次请求默认返回的数据条数是10条,可以通过设置size参数来控制返回数据的条数: 如果要返回很多数据,可以把size设置的很大,不过elastic search默认size最大不能超过1万. 那 ...

  9. 贪玩ML系列之CIFAR-10调参

    调参方法:网格调参 tf.layers.conv2d()中的padding参数 取值“same”,表示当filter移出边界时,给空位补0继续计算.该方法能够更多的保留图像边缘信息.当图片较小(如CI ...

  10. java中byte[] 和16进制字符串互转

    //将byte[]转换为16进制字符串 public static String byte2hex(byte[] b) { StringBuilder hs = new StringBuilder() ...