问题聚焦:
自我赋值看似有点愚蠢的行为,其实总会发生的
首先:它是合法的,
其次,它不一定是安全的,
再次,它有时候不是那么明显。

先看一个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;
}

改进方案二:copy and swap

class Widget {
...
void swap(Widget& rhs);
...
}; Widget& Widget::operator=(const Wdiget& rhs)
{
Widget temp(rhs);
swap(temp);
return *this;
}

思想:
拷贝构造函数要声明为“按值传递”
按值传递会造成一份副本
小结:

确保当对象自我赋值时operator=有良好的行为。

包括:

对象来源

目标对象地址

语句顺序

确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。

参考资料:
《Effective C++ 3rd》

Effective C++(11) 自我赋值(a=a)时会发生什么?的更多相关文章

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

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

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

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

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

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

  4. Effective C++ 条款11:在operator=中处理"自我赋值"

    "自我赋值"发生在对象被赋值给自己时: class Widget { ... }; Widget w; ... w = w; // 赋值给自己 a[i] = a[j]; // 潜在 ...

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 【iOS发展-81】setNeedsDisplay刷新显卡,并CADisplayLink它用来模拟计时器效果

    (1)效果 (2)源码下载(假设提示没有小图片的话,自己找一个替换一下即可,看到效果即可) http://download.csdn.net/detail/wsb200514/8176339 (3)总 ...

  2. 如何用Excel直接查询Oracle中的数据(转)

    将Oracle中查询的数据保存为Excel文件,通常使用的是PL/SQL Developer. 其实,Excel可直接写SQL语句查询Oracle中数据,在这里,用到ODBC驱动.详细步骤如下: 一. ...

  3. 移植X264成功

    http://blog.csdn.net/mashang123456789/article/details/8673426 http://blog.csdn.net/b5w2p0/article/de ...

  4. HTML DOM的nodeName,nodeValue,nodeType介绍

    将HTML DOM中几个常用的属性做下介绍,工作中作为参考. nodeName 属性可依据节点的类型返回其名称. 元素节点的 nodeName 是标签名称 属性节点的 nodeName 是属性名称 文 ...

  5. T4模板使用技巧

    =============C#.Net 篇目录============== 示例代码:示例代码__你必须懂的T4模板:浅入深出.rar (一)什么是T4模板? T4,即4个T开头的英文字母组合:Tex ...

  6. Cocos2d-x实现Android的Toast特征

    1.Toast Android的Toast是View视图,显示少量的信息.主要用于一些提示和帮助.本文实现了Toast最主要的操作能, 代码例如以下: //PacToast.h #include &q ...

  7. HDU 1243 畅通project 并査集

    Total Submission(s): 31033    Accepted Submission(s): 16313 Problem Description 某省调查城镇交通状况,得到现有城镇道路统 ...

  8. [CLR via C#]1.5 本地代码生成器:NGen.exe

    原文:[CLR via C#]1.5 本地代码生成器:NGen.exe 1. NGen.exe工具,可以在一个程序安装到用户计算机时,将IL代码编译成为本地代码.由于代码在安装时已经编译好,所以CLR ...

  9. Java初认识--函数和数组

    一.函数 1.函数的定义 函数就是定义在类中的具有特定功能的一段独立小程序,函数也称为方法. java中最小的功能单元就是函数. 2.函数的格式 修饰符 返回值类型 函数名(参数类型 形式参数1,参数 ...

  10. wget一个小技巧

    今天在装一个东西的时候,在网上看到了这样的命令 wget  http://xxxx.sh -o -  | sh  的用法 不太明白-o -的用法于是乎man wget,看到了下面的一段话 -O fil ...