zoukankan      html  css  js  c++  java
  • 条款11:在operator=中处理“自我赋值”

    什么是自我赋值,就是 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 }
  • 相关阅读:
    一幅图解决R语言绘制图例的各种问题
    新时代,建立你的数据分析思维
    新时代,建立你的数据分析思维
    聚类分析基础知识总结及实战解析
    聚类分析基础知识总结及实战解析
    js中 opener和parent的差别
    Latex中參考文献排序
    Android之——清理手机SD卡缓存
    drupal7 使用(hook_preprocess_HOOK)向各个主题模版里面传递变量
    python 正則表達式推断邮箱格式是否正确
  • 原文地址:https://www.cnblogs.com/benxintuzi/p/4530556.html
Copyright © 2011-2022 走看看