Google Refptr

2019-12-19

最近工作中发现了一个关于智能指针的=运算符重载的经典代码实现,记录一下:

  scoped_refptr& operator=(std::nullptr_t) {
    reset();
    return *this;
  }
  // Sets managed object to null and releases reference to the previous managed
  // object, if it existed.
  void reset() { scoped_refptr().swap(*this); }

  scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
  // Unified assignment operator.
  scoped_refptr& operator=(scoped_refptr r) noexcept {
    swap(r);
    return *this;
  }
  void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); }

可以只看operator=(std::nullptr_t), 由于将this赋值给null,所以this需要释放。此时operator=这个函数不好实现,因为如果在函数退出前释放的话,释放后的任何操作都相当于操作了已释放对象(可参考附录1我在pr中的描述)。

这里的google的实现是:将this和一个临时变量进行swap, 该临时对象的ptr_为null,交换后临时对象的ptr_变成了this->ptr_,this->ptr_变成了null,这是前提。然后经典的来了,当reset函数退出时,

临时变量退出了其作用区域,会被释放,根据指针的特性,其对应的其ptr_指向的空间也会释放,由于此时临时对象的ptr_是this->ptr_,所以reset退出时,实际释放的是this->ptr_。

下面的几个函数原理是一样的,这里就不解释了

具体代码文件:https://chromium.googlesource.com/chromium/src/+/master/base/memory/scoped_refptr.h

附录1:https://github.com/XiaoMi/rdsn/pull/361