C++智能指针的简单实现auto_ptr、unique_ptr、shared_ptr

实现的方式或许有些问题,可以指出来一起交流一下呢

/**
 * RAII(资源获取即初始化)技术使用局部变量的生存周期来控制堆上的数据或者是来控制文件的关闭,
 * 局部变量超过其作用域之后就会被释放
   智能指针的简单实现auto_ptr,unique_ptr,shared_ptr
*/
#include 
#include 
#include 
namespace zpc{
      /**
       * auto_ptr是一种比较早的智能指针,其可以被拷贝存在隐患
      */
      template<class __Tp>
      class auto_ptr{
          private:
              __Tp* ptr;
          public:
              auto_ptr() = default;
              explicit auto_ptr(__Tp* ptr):ptr(ptr){}
              auto_ptr(const auto_ptr& other){
                  ptr = other.release();
              }
              void operator =(const auto_ptr<__Tp>& other){
                  ptr = other.release();
              }
              __Tp* release(){
                  __Tp* tmp = ptr;
                  ptr = nullptr;
                  return tmp;
              }
              // 这里的const 修饰的是 this 指针 const auto_ptr* const this
              // this指针本身就是一个指针常量, 
              // 这里返回 ptr 不存在const 修饰的时候可能会造成ptr指向修改 (*this).ptr
              // 值得注意的是 *ptr 是可以修改的 const 修饰的是this指针 不存在贯穿作用
              __Tp* get()const{
                   return ptr;
              }
              __Tp& operator *()const{
                    return *get();
              }
              __Tp* operator ->(){
                    return get();
              } 
              ~auto_ptr(){
                  if(ptr != nullptr){
                      delete ptr;
                      ptr = nullptr;
                  }
              }    
      };
      /**
       * unique_ptr 是对 auto_ptr 做出的改进, 不允许拷贝构造的使用
       * 但是可以使用移动语义
      */
      template<class __Tp>
      class unique_ptr{
            private:
               __Tp* ptr;
            public:
                unique_ptr() = default;
                explicit unique_ptr(__Tp* ptr):ptr(ptr){}
                // 拷贝构造 在unique_ptr 中删除尽可以使用移动语义来进行
                unique_ptr(unique_ptr<__Tp>& other) = delete;
                // 移动构造
                unique_ptr(unique_ptr<__Tp>&& other){
                      this->ptr = other.release();
                }
                // 拷贝等号赋值符
                unique_ptr<__Tp>& operator =(unique_ptr<__Tp>&other) = delete;
                // 移动等号赋值符
                unique_ptr<__Tp>& operator =(unique_ptr<__Tp>&& other){
                      this->ptr = other.release();
                      return *this;
                }
                __Tp* release(){
                    __Tp* tmp = ptr;
                    ptr = nullptr;
                    return ptr;
                }
                inline __Tp* get()const{
                     return ptr;
                }
                __Tp& operator*()const{
                     return *get();
                }
                __Tp* operator->()const{
                     return get();
                }
                ~unique_ptr(){
                    if( ptr != nullptr){
                         delete ptr;
                         ptr = nullptr;
                    }
                }
      };
      /**
       * shared_ptr 是共享指针 这里需要注意一下这个引用计数是创建在堆上的
       * 不要认为是static修饰的, static修饰的是属于整个类上的
       * shared_ptr 是线程不安全的, 但是不是引用计数的问题
       * 在多线程如果是使用引用传递shared_ptr的时候,多个线程都是传递引用(操作的是同一个),
       *  在有的多线程中改变了shared_ptr的指向,可能会导致这个shared_ptr 的引用计数变成 0 从而销毁
      */
      template<class __Tp>
      class shared_ptr{
         private:
            std::mutex mtx;
            int* count;
            __Tp* ptr;
         public:
            shared_ptr() = default;
            explicit shared_ptr(__Tp* ptr):ptr(ptr){
                  count = new int(1);
            }
            // 拷贝构造使用浅拷贝
            shared_ptr(const shared_ptr<__Tp>& other){ 
                  ptr = other.ptr;
                  count = other.count;
                  AddReferenceCount();
            }
            // 移动拷贝构造, 资源的转移
            shared_ptr(shared_ptr<__Tp>&& other){
                  ptr = other.ptr;
                  count = other.count;
                  other.ptr = nullptr;
                  other.count = nullptr;
            }
            // ptr1 = ptr2 相同空间不可以
            // ptr1 != ptr2 不同空间需要先释放当前的空间, 
            shared_ptr<__Tp>& operator =(shared_ptr<__Tp>& other){
                  if( ptr != other.ptr ){
                        Realse();
                        ptr = other.ptr;
                        count = other.count;
                        AddReferenceCount();
                  }
                  return *this;
            }
            shared_ptr<__Tp>& operator =(shared_ptr<__Tp>&& other){
                  if(ptr != other.ptr){
                       Realse();
                       ptr = other.ptr;
                       count = other.count;
                       other.ptr = nullptr;
                       other.count = nullptr;
                  }
                  return *this;
            }
            int const& ReferenCount() const{
                  return *count;
            }
            void AddReferenceCount(){
                  // unique_lock实现自动加锁解锁
                  std::unique_lock<std::mutex>lock(mtx);
                  ++(*count);
            }
            void SubReferenceCount(){
                  std::unique_lock<std::mutex>lock(mtx);
                  --(*count);
            }
            ~shared_ptr(){
                 if(ptr != nullptr){
                       Realse();     
                 }
            }
            void Realse(){
                  SubReferenceCount();
                  if(*count == 0){
                        delete ptr;
                        delete count;    
                        ptr = nullptr;
                        count = nullptr;
                  }
            }
            __Tp* get()const{
                  return ptr;
            }
            __Tp& operator*(){
                  return *get();
            }
            __Tp* operator->(){
                  return get();
            }
              
      };
      template<class __Tp>
      unique_ptr<__Tp> make_unique(__Tp value){
          return unique_ptr<__Tp>(new __Tp(value));
      }
      template<class __Tp>
      shared_ptr<__Tp> make_shared(__Tp value){
            return shared_ptr<__Tp>(new __Tp(value));
      }
};
class Info{
      private:
         int num;
      public:
          Info() = default;
          Info(int num):num(num){
                std::cout<<"create"<<std::endl;
          }
          Info(Info& other):num(other.num){
                std::cout<<"copy create"<<std::endl;
          }
          Info(Info&& other):num(other.num){
                std::cout<<"moving create"<<std::endl;
                other.num = NULL;

          }
          void operator =(Info& other){
                std::cout<<"operator = copy"<<std::endl;
                num = other.num;
          }
          void operator =(Info&& other){
                std::cout<<"operator = moving"<<std::endl;
                num = other.num;
                num = NULL;
          }
          ~Info(){
             std::cout<<"delete"<<std::endl;
          };
          int get(){
              return num;
          }
};
int main(){ 
      {     
            Info* info = new Info(4);
            zpc::unique_ptr<Info>ptr(info);
            zpc::unique_ptr<Info>ptr2 = zpc::make_unique<Info>(4);
      }
      {
            Info* info = new Info(4);
            zpc::shared_ptr<Info>ptr1(info);
            zpc::shared_ptr<Info>ptr2(ptr1);
            zpc::shared_ptr<Info>ptr3(ptr2);
            std::cout<<ptr1.ReferenCount()<<std::endl;
            std::cout<<ptr2.ReferenCount()<<std::endl;
            std::cout<<ptr3.ReferenCount()<<std::endl;
            // 转移ptr3 的指向的时候, 原有的引用计数-1
            ptr3 = zpc::make_shared<Info>(4);
            std::cout<<ptr1.ReferenCount()<<std::endl;
            std::cout<<ptr2.ReferenCount()<<std::endl;    
      }
 

    
  
      std::getchar();

}

你可能感兴趣的:(c++)