benxintuzi

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

什么是自我赋值,就是 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 }

 

posted on 2015-05-26 14:24  benxintuzi  阅读(427)  评论(0编辑  收藏  举报