手撕STL系列之智能指针
C++11智能指针:
- shared_ptr: 基于引用计数实现
 
- unique_ptr: 不可以移动的智能指针
 
- weak_ptr: 解决shared_ptr循环引用问题,更加类似于shared_ptr的管理指针工具。
 
shared_ptr
shared_ptr是基于引用计数实现,可在生命周期内自动管理内存
我们先实现一个应用计数的类,用atomic实现,保证线程安全:
 class SharedCount { public:     SharedCount() : count(1) {}
      void add()     {         count++;     }
      void minus()     {         count--;     }
      int get() const     {         return count;     }
  private:     std::atomic<int> count;
  };
 
  | 
 
实现shared_ptr注意点:
- 实现赋值构造函数和移动构造函数,
 
- 重写拷贝赋值和移动赋值符号
 
- 再就是shared_ptr的一些其他函数,比如use_count(),get()等方法
 
- 管理引用计数,在计数==1的时候删除内存。
 
#include <iostream> #include <memory> #include <atomic>
  using namespace std;
 
  template <typename T> class SharedPtr{
  public:          SharedPtr() : ptr(nullptr), ref_count(new SharedCount()) {}
      explicit SharedPtr(T* _ptr) : ptr(_ptr), ref_count(new SharedCount()) {}
           SharedPtr(const SharedPtr& _s_ptr)     {         this->ptr = _s_ptr.ptr;         this->ref_count = _s_ptr.ref_count;         ref_count->add();     }
      SharedPtr& operator=(const SharedPtr& _s_ptr)     {         clean();         this->ptr = _s_ptr.ptr;         this->ref_count = _s_ptr.ref_count;         ref_count->add();         return *this;     }
           SharedPtr(SharedPtr&& _s_ptr)     {         this->ptr = _s_ptr.ptr;         this->ref_count = _s_ptr.ref_count;         _s_ptr.ptr = nullptr;         _s_ptr.ref_count = nullptr;     }
           SharedPtr& operator=(SharedPtr&& _s_ptr)     {         clean();         this->ptr = _s_ptr.ptr;         this->ref_count = _s_ptr.ref_count;         _s_ptr.ptr = nullptr;         _s_ptr.ref_count = nullptr;         return *this;     }
           T* get() const     {         return ptr;     }
      T& operator* () const     {         return  *ptr;     }
      T* operator-> () const     {         return ptr;     }
      int use_count()     {         return ref_count->get();     }
      ~SharedPtr(){         clean();     }
  private:     T* ptr;     SharedCount* ref_count;
      void clean()     {         if (ref_count)         {             ref_count->minus();             if (ref_count->get() == 0)             {                 if(ptr) delete ptr;                 delete ref_count;             }         }     }
  };
 
 
   | 
 
shared_ptr之间有个强制转换static_pointer_cast:具体实现
template<typename T, typename U> SharedPtr<T> static_pointer_cast(const SharedPtr<U>& up) {     T* ptr = static_cast<T*>(up.get());     return SharedPtr(up,ptr); }
 
 
 
 
  template<typename U> friend class SharedPtr;
  template<typename U> SharedPtr(const SharedPtr<U>& up, T* tp) {     this->ptr = tp;     this->ref_count = up.ref_count;     ref_count->add(); }
 
   | 
 
测试:
 class A { public:     A() { std::cout << "A() \n"; }     ~A() { std::cout << "~A() \n"; } };
  class B : public A { public:     B() { std::cout << "B() \n"; }     ~B() { std::cout << "~B() \n"; } };
 
  void test_shared_ptr() {     SharedPtr<size_t> ptr1(new size_t(110));     cout << ptr1.use_count() << endl;   
      {         SharedPtr<size_t> ptr2 = ptr1;         cout << ptr1.use_count() << endl;   
          SharedPtr<size_t> ptr3(ptr1);         cout << ptr1.use_count() << endl;   
          SharedPtr<size_t> ptr4 = std::move(ptr2);         cout << ptr4.use_count() << endl;        }
      cout << ptr1.use_count() << endl;   
  }
  void test_static_cast() {     B* b = new B();     SharedPtr<B> ptr(b);     cout << ptr.use_count() << endl;     {         SharedPtr<A> ptr_a = static_pointer_cast<A,B>(ptr);         cout << ptr_a.use_count() << endl;     }     cout << ptr.use_count() << endl; }
  int main(){          test_static_cast(); };
 
 
  | 
 
unique_ptr
特点:
- 没有引用计数
 
- 禁止拷贝赋值
 
#include <iostream>
 
  template<typename T> class unique_ptr { private:     T* ptr;
      void clean()     {         if (ptr)         {             delete ptr;             ptr = nullptr;         }     }
 
  public:     unique_ptr() : ptr(nullptr) {}
      unique_ptr(T* ptr) : ptr(ptr) {}
 
      unique_ptr(unique_ptr& u_ptr) = delete;     unique_ptr& operator=(unique_ptr& u_ptr) = delete;
      unique_ptr(unique_ptr&& u_ptr)     {         this->ptr = u_ptr.ptr;         u_ptr.ptr = nullptr;     }
      unique_ptr& operator=(unique_ptr&& u_ptr)     {         clean();         this->ptr = u_ptr.ptr;         u_ptr.ptr = nullptr;         return *this;     }
      T* get() const     {         return ptr;     }
      T* operator->() const     {         return ptr;     }
      T& operator*() const     {         return *ptr;     }
      ~unique_ptr()     {         clean();     } };
 
   | 
 
weak_ptr
weak_ptr是弱智能指针对象,它不控制所指向对象生存期的智能指针,它指向由一个shared_ptr管理的智能指针。将一个weak_ptr绑定到一个shared_ptr对象,不会改变shared_ptr的引用计数。一旦最后一个所指向对象的shared_ptr被销毁,所指向的对象就会被释放,即使此时有weak_ptr指向该对象,所指向的对象依然被释放。
 void checkwp(weak_ptr<string>& wp) {          if (!wp.expired())     {                  auto sp = wp.lock();         std::cout << *sp << std::endl;     }     else     {         std::cout << "wp expired" << std::endl;     } }
 
  void test() {     shared_ptr<string> sp1 = make_shared<string>("bug maker!");
           weak_ptr<string> wp1 = sp1;     weak_ptr<string> wp2(sp1);     weak_ptr<string> wp3 = wp2;
      checkwp(wp1);
           wp1.reset();     checkwp(wp1);
           checkwp(wp2);
           std::cout <<  (wp2.lock() == wp3.lock() ? "true" : "false") << std::endl;     std::cout <<  (sp1 == wp2.lock() ? "true" : "false") << std::endl;
  }
  bug maker! wp expired bug maker! true true
 
 
  | 
 
实现weak_ptr的注意点在于:
- 只能使用shared_ptr和weak_ptr来构造weak_ptr
 
- 没有自己的数据成员,而是只提供了一些供调用的接口
 
- 没有重载operator *,operator-> 函数
 
辅助函数:
- reset 释放被管理对象的所有权。调用后*this不管理对象
 
- swap 交换被管理对象,只能与其他weak_ptr对象交换。不调整引用计数
 
- use_count() 返回管理该资源对象的shared_ptr指针对象的数量
 
- expired() 检直被引用的资源对象是否已删除
 
- Iock() 创建管理被引用的对象的shared_ptr,是线性安全的
 
参考: