[cpp32 note] 2. 实现cpp智能指针 (1)

将上一节的RAII代码模板化,
并且添加&、->、bool等运算符重载:

template <typename T>
class smart_ptr {
 public:
  explicit smart_ptr(T* ptr = nullptr) : ptr_(ptr) {}
  ~smart_ptr() { delete ptr_; }
  T* get() { return ptr_; }
  T& operator*() const { return *ptr_; }
  T* operator->() const { return ptr_; }
  operator bool() const { return ptr_; }

 private:
  T* ptr_;
};

目前的代码,在拷贝时会赋值对象指针,有内存释放两次的隐患,
我们可以禁用 拷贝构造和赋值,避免对象指针的复制:

template <typename T>
class smart_ptr {
 public:
  smart_ptr(const smart_ptr&) = delete;
  smart_ptr& operator=(const smart_ptr&) = delete;

 private:
  T* ptr_;
};

也可以在复制时转移对象指针的所有权:
这里的赋值分为拷贝构造和swap两步

  1. 首先是smart_ptr(rhs),调用了拷贝构造,
    生成了一个临时变量,拿出了rhs的指针所有权
  2. 然后与临时变量交换指针所有权

异常只可能出现在拷贝构造部分。
分成两步是为了防止在拷贝的过程中出现异常,导致当前对象收到影响。

template <typename T>
class smart_ptr {
 public:
  explicit smart_ptr(T* ptr = nullptr) : ptr_(ptr) {}
  ~smart_ptr() { delete ptr_; }

  smart_ptr(smart_ptr& other) { ptr_ = other.release(); }
  // 这里的参数可以直接把引用改成拷贝
  // 这样的话函数内部就不需要自己创建临时变量了
  smart_ptr& operator=(smart_ptr& rhs) {
    smart_ptr(rhs).swap(*this);
    return *this;
  }

  // 交出指针所有权
  T* release() {
    T* ptr = ptr_;
    ptr_ = nullptr;
    return ptr;
  }

  // 交换指针
  void swap(smart_ptr& rhs) { std::swap(ptr_, rhs.ptr_); }

  T* get() { return ptr_; }
  T& operator*() const { return *ptr_; }
  T* operator->() const { return ptr_; }
  operator bool() const { return ptr_; }

 private:
  T* ptr_;
};

上面的实现其实很不合理,因为没有显式的告诉你拷贝会转移指针所有权,
在使用时容易不小心把指针传走了。

可以在使用移动构造时,才转移指针所有权:
(cpp里如果提供了移动构造,那么拷贝构造是默认禁用的,不需要再显式禁用)

template <typename T>
class smart_ptr {
 public:
  explicit smart_ptr(T* ptr = nullptr) : ptr_(ptr) {}
  ~smart_ptr() { delete ptr_; }

  smart_ptr(smart_ptr&& other) { ptr_ = other.release(); }
  //赋值时,参数以拷贝的方式传入,不再需要手动创建临时变量
  smart_ptr& operator=(smart_ptr rhs) {
    rhs.swap(*this);
    return *this
  }

  // 交出指针所有权
  T* release() {
    T* ptr = ptr_;
    ptr_ = nullptr;
    return ptr;
  }

  // 交换指针
  void swap(smart_ptr& rhs) { std::swap(ptr_, rhs.ptr_); }

  T* get() { return ptr_; }
  T& operator*() const { return *ptr_; }
  T* operator->() const { return ptr_; }
  operator bool() const { return ptr_; }

 private:
  T* ptr_;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值