zoukankan      html  css  js  c++  java
  • 条款十七: 在operator=中检查给自己赋值的情况

    在赋值运算符中要特别注意可能出现别名的情况,其理由基于两点。其中之一是效率。如果可以在赋值运算符函数体的首部检测到是给自己赋值,就可以立即返回,从而可以节省大量的工作,否则必须去实现整个赋值操作。

    另一个更重要的原因是保证正确性。一个赋值运算符必须首先释放掉一个对象的资源(去掉旧值),然后根据新值分配新的资源。在自己给自己赋值的情况下,释放旧的资源将是灾难性的,因为在分配新的资源时会需要旧的资源。

    看看下面string对象的赋值,赋值运算符没有对给自己赋值的情况进行检查:

    class string {
    public:
      string(const char *value);    // 函数定义参见条款11
                                    // 
    
      ~string();                    // 函数定义参见条款11
                                    // 
      ...
    
      string& operator=(const string& rhs);
    
    private:
      char *data;
    };
    
    // 忽略了给自己赋值的情况
    // 的赋值运算符
    string& string::operator=(const string& rhs)
    {
      delete [] data;    // delete old memory
    
      // 分配新内存,将rhs的值拷贝给它
      data = new char[strlen(rhs.data) + 1];
      strcpy(data, rhs.data);
    
      return *this;      // see item 15
    }

    现在可以知道,解决问题的方案是对可能发生的自己给自己赋值的情况先进行检查,如果有这种情况就立即返回。不幸的是,这种检查说起来容易做起来难,因为你必须定义两个对象怎么样才算是“相同”的。

    一个确定对象身份是否相同的方法是用内存地址。采用这个定义,两个对象当且仅当它们具有相同的地址时才是相同的。这个定义在c++程序中运用更广泛,可能是因为它很容易实现而且计算很快,而采用值相等的定义则不一定总具有这两个优点。采用地址相等的定义,一个普通的赋值运算符看起来象这样:

    c& c::operator=(const c& rhs)
    {
      // 检查对自己赋值的情况
      if (this == &rhs) return *this;
    
      ...
    
    }
  • 相关阅读:
    OCP-1Z0-052-V8.02-116题
    OCP-1Z0-052-V8.02-6题
    OCP-1Z0-052-V8.02-5题
    使用rman恢复控制文件
    Matlab-质点的运动
    Matlab中checkerboard-创建棋盘图像(二)
    OCP-1Z0-052-V8.02-4题
    OCP-1Z0-052-V8.02-3题
    Matlab中checkerboard-创建棋盘图像(一)
    OCP-1Z0-052-V8.02-1题
  • 原文地址:https://www.cnblogs.com/ljygoodgoodstudydaydayup/p/3904635.html
Copyright © 2011-2022 走看看