码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-05-26 15:57:37      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:

什么是自我赋值,就是 v = v 这种类型的语句,也许很多人都会说鄙视这种写法,但是如下的写法会不会出现呢?

比如:a[i] = a[j];      // 不巧的是i可能和j相等

           *px = *py;     // 也许px和py刚好指向同一个对象呢

上述例子都是隐含的自我赋值。

再举一例:

 1 class Bitmap              // 位图类
 2 {
 3     ...
 4 };
 5 
 6 class Widget
 7 {
 8 public:
 9     Widget& operator=(const Widget& rhs);
10     
11 private:
12     Bitmap* pb;           // 指向动态分配的位图对象
13 };
14 
15 Widget& Widget::operator=(const Widget& rhs)
16 {
17     delete pb;                  // 释放当前位图对象
18     pb = new Bitmap(*rhs.pb);   // 使用rhs中位图的副本
19     return *this;
20 }

现在假设*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技术,如下所示:

 1 class Widget
 2 {
 3     ...
 4     void swap(Widget& rhs);     // 交换*this和rhs的内容
 5     ...
 6 };
 7 
 8 Widget& Widget::operator=(const Widget& rhs)
 9 {
10     Widget temp(rhs);           // 制作一个rhs的副本
11     swap(temp);                 // 将该副本内容和*this交换
12     return *this;
13 }

 

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

标签:

原文地址:http://www.cnblogs.com/benxintuzi/p/4530556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!