美文网首页
C++中operator=实现处理自我赋值

C++中operator=实现处理自我赋值

作者: b036101467d7 | 来源:发表于2019-05-27 11:34 被阅读0次

copy构造以及operator=操作符,其实都是拷贝class的私有变量,例如以下Test类,拷贝的为成员变量mData指向的数据,以及mDataLen的值

class Test {
public:
        Test &operator=(const Test &copy);
private:
    uint8_t *mData;
    int mDataLen;
};
  1. 自然想到的实现方法:
Test &operator=(const Test &copy) {
      if(this.mData) {
          free(this.mData);
      }
      this.mData = (uint8_t *)malloc(copy.mDataLen);
      this.mDataLen = copy.mDataLen;
      memcpy(mData, copy.mData, copy.mDataLen);
      return *this; 
}
  1. 上述1的实现可能出现对象自我赋值,修改为:
Test &operator=(const Test &copy) {
      if(this == &copy) {
          return *this;
      }
      if(this.mData) {
          free(this.mData);
      }
      this.mData = (uint8_t *)malloc(copy.mDataLen);
      if(this.mData == NULL) return *this;
      this.mDataLen = copy.mDataLen;
      memcpy(mData, copy.mData, copy.mDataLen);
      return *this; 
}
  1. 上述2的实现,在malloc的时候,可能出现异常,应确保没有资源泄漏,并尽量保持原状态,
    修改为以下,在新内存创建成功情况下,再释放原内存,因此已经避免了自我赋值,因此可以将相关语句去掉:
Test &operator=(const Test &copy) {
      uint8_t *pOriData = this.mData;

      this.mData = (uint8_t *)malloc(copy.mDataLen);
      if(this.mData == NULL) return *this;
      this.mDataLen = copy.mDataLen;
      memcpy(mData, copy.mData, copy.mDataLen);

      if(this.pOriData) {
          free(this.pOriData);
      }

      return *this; 
}
  1. 上述3的实现实际是 copy and swap技术,因此可以使用标准库函数swap,
    首先std::swap保证了不会出现异常,其次swap操作对象,只是做指针的转换,效率更高,
    但注意是拷贝,不能影响被拷贝者的值,因此只能使用被拷贝者的副本执行swap操作:
Test &operator=(const Test &copy) {     
      Test  temp(copy);
      std::swap(*this, temp);
      return *this; 
}
  1. 还有一种实现,参数传值代替传引用,将“拷贝动作”由函数体移到了函数参数构造阶段,可能会另编译器生成更高效的代码,为operator=的接口一致性,还是建议使用4的实现:
Test &operator=(const Test copy) {     
      std::swap(*this, copy);
      return *this; 
}

相关文章

网友评论

      本文标题:C++中operator=实现处理自我赋值

      本文链接:https://www.haomeiwen.com/subject/lipctctx.html