• C++——智能指针shared_ptr的实现


    1. 起初,我最直观的设计想法,直接设计一个类:包含全部要素(对象,指针计数)。然后提供出去。
     1 class CPoint
     2 {
     3   public:
     4     CPoint(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) {}
     5     int getX() const { return x; }
     6     int getY() const { return y; }
     7     void setX(int xVal) { x = xVal; }
     8     void setY(int yVal) { y = yVal; }
     9 
    10   private:
    11     int x, y;
    12 };
    13 
    14 class CSmartPtr
    15 {
    16   public:
    17     CSmartPtr(CPoint *ptr) : m_pPoint(ptr),m_count(1) {}
    18     CSmartPtr(const CSmartPtr &sptr) : m_pPoint(sptr.m_pPoint),m_count(sptr.m_count) {}
    19 
    20     ~CSmartPtr()
    21     {
    22         Release();
    23     }
    24     CPoint* get()
    25     {
    26         return m_pPoint;
    27     }
    28 /*此处不知道如何有效实现,既能提供出去,有把内部清空????*/
    29     CPoint *release()
    30     {
    31         m_count = 0;
    32         return m_pPoint;
    33     }
    34     int user_count() { return m_count; }
    35     CPoint &operator*()
    36     {
    37         return *(m_pPoint);
    38     }
    39 
    40     CPoint *operator->()
    41     {
    42         return m_pPoint;
    43     }
    44 
    45   private:
    46     void Release()
    47     {
    48         if (m_count-- == 0)
    49         {
    50             delete m_pPoint;
    51         }
    52         else
    53         {
    54             cout << "引用次数:" << m_count << endl;
    55         }
    56     }
    57 
    58     int m_count;
    59     CPoint *m_pPoint;
    60 };

    但是我实现到release方法的时候,并不能满足需求。因为release方法的要求是,交出对象的控制权,然后智能指针指向null;Releases ownership of its stored pointer, by returning its value and replacing it with a null pointer.这就尴尬了。因此采用了将指针计数和对象单独拿出来的做法,也就是网上其他博客中常见的做法。但我还不是很理解他们那种做法的解释。

     

          代码实现:

      1 class CPoint
      2 {
      3   public:
      4     CPoint(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) {}
      5     int getX() const { return x; }
      6     int getY() const { return y; }
      7     void setX(int xVal) { x = xVal; }
      8     void setY(int yVal) { y = yVal; }
      9 
     10   private:
     11     int x, y;
     12 };
     13 class CSmartPtr;
     14 /*
     15 
     16 */
     17 class CCountPtr
     18 {
     19     private:
     20         friend class CSmartPtr;
     21         int m_count;
     22         CPoint *m_pPoint;
     23         CCountPtr(CPoint *ptr):m_pPoint(ptr),m_count(1){}
     24         ~CCountPtr()
     25         {
     26             m_count=0;
     27         }
     28 };
     29 
     30 class CSmartPtr
     31 {
     32     public:
     33       CSmartPtr(CPoint *ptr) : m_pCountPtr (new CCountPtr(ptr)){}
     34       CSmartPtr(const CSmartPtr &sptr) : m_pCountPtr(sptr.m_pCountPtr) {}
     35       CSmartPtr& operator=(const CSmartPtr &sptr)
     36       {
     37           (sptr.m_pCountPtr->m_count)++;
     38           minusOne();
     39           m_pCountPtr = sptr.m_pCountPtr;
     40           return *this;
     41       }
     42       ~CSmartPtr() 
     43       {
     44           minusOne();
     45       }
     46       CPoint *get()
     47       {
     48           return m_pCountPtr->m_pPoint;
     49       }
     50       CPoint *release()
     51       {
     52           CPoint *pRet = m_pCountPtr->m_pPoint;
     53           m_pCountPtr->m_pPoint = nullptr;
     54           m_pCountPtr->m_count  = 0;
     55           return pRet;
     56       }
     57       /*Destroys the object currently managed by the unique_ptr (if any) and takes ownership of p.*/
     58       void reset(CPoint *pPoint)
     59       {
     60           minusOne();
     61           m_pCountPtr = new CCountPtr(pPoint);
     62       }
     63       void swap(CSmartPtr &x)
     64       {
     65           CPoint *pRet = m_pCountPtr->m_pPoint;
     66           int count = m_pCountPtr->m_count;
     67 
     68           m_pCountPtr->m_pPoint = x.m_pCountPtr->m_pPoint;
     69           m_pCountPtr->m_count = x.m_pCountPtr->m_count;
     70 
     71           x.m_pCountPtr->m_pPoint = pRet;
     72           x.m_pCountPtr->m_count = count;
     73       }
     74 
     75       int user_count(){return m_pCountPtr->m_count; }
     76       CPoint& operator *()
     77       {
     78           return *(m_pCountPtr->m_pPoint);
     79       }
     80 
     81       CPoint* operator ->()
     82       {
     83           return m_pCountPtr->m_pPoint;
     84       }
     85 
     86     private:
     87       void minusOne()
     88       {
     89           if (m_pCountPtr->m_count-- == 0)
     90           {
     91               delete m_pCountPtr;
     92               m_pCountPtr = nullptr;
     93           }
     94           else
     95           {
     96               cout << "引用次数:" << m_pCountPtr->m_count << endl;
     97           }
     98       }
     99       CCountPtr *m_pCountPtr;
    100 };
    101 
    102 int main()
    103 {
    104     CPoint *pPoint = new CPoint(3,4);
    105     {
    106         CSmartPtr sptr1(pPoint);
    107         {
    108             (*sptr1).setX(10);
    109             cout<<"initial:"<<endl;
    110             cout << "sptr1->getX(): " << sptr1->getX() << endl;
    111             CPoint *pPoint2 = new CPoint(5, 6);
    112             /*测试swap*/
    113             cout << "swap:" << endl;
    114             CPoint *pPoint4 = new CPoint(30, 40);
    115             CSmartPtr sptr2(pPoint4);
    116             sptr1.swap(sptr2);
    117             cout << "sptr1->getX(): " << sptr1->getX() << endl;
    118             cout << "sptr2->getX(): " << sptr2->getX() << endl;
    119             /*测试reset*/
    120             cout << "reset:" << endl;
    121             sptr1.reset(pPoint2);
    122             cout << "sptr1->getX(): " << sptr1->getX() << endl;
    123             /*测试release*/
    124             cout << "release:" << endl;
    125             CPoint *pPoint3 = new CPoint(30, 40);
    126             pPoint3 = sptr1.release();
    127             cout << "pPoint3->getX(): " << pPoint3->getX() << endl;
    128             cout << "sptr1.count: " << sptr1.user_count() << endl;
    129         }
    130         cout<<"sptr1.count: "<< sptr1.user_count()<<endl;
    131     }
    132 
    133     cout<<"pPoint.getx(): "<<pPoint->getX()<<endl;
    134     system("pause");
    135     return 0;
    136 }

           2.模板类。改进一下即可。将CPoint换成泛型表达。

      1 template <typename T>
      2 class CSmartPtr;
      3 
      4 template <typename T>
      5 class CCountPtr
      6 {
      7     private:
      8         friend class CSmartPtr<T>;
      9         int m_count;
     10         T *m_pT;
     11         CCountPtr(T *ptr) : m_pT(ptr), m_count(1) {}
     12         ~CCountPtr(){}
     13 };
     14 
     15 template <typename T>
     16 class CSmartPtr
     17 {
     18     public:
     19       CSmartPtr(T *ptr) : m_pCountPtr (new CCountPtr<T>(ptr)){}
     20       CSmartPtr(const CSmartPtr &sptr) : m_pCountPtr(sptr.m_pCountPtr) {}
     21       CSmartPtr& operator=(const CSmartPtr &sptr)
     22       {
     23           (sptr.m_pCountPtr->m_count)++;
     24           minusOne();
     25           m_pCountPtr = sptr.m_pCountPtr;
     26           return *this;
     27       }
     28 
     29       ~CSmartPtr() 
     30       {
     31           minusOne();
     32       }
     33       T * get()
     34       {
     35           return m_pCountPtr->m_pPoint;
     36       }
     37       T *release()
     38       {
     39           T *pRet = m_pCountPtr->m_pPoint;
     40           m_pCountPtr->m_pPoint = nullptr;
     41           m_pCountPtr->m_count = 0;
     42           return pRet;
     43       }
     44       /*Destroys the object currently managed by the unique_ptr (if any) and takes ownership of p.*/
     45       void reset(T *pPoint)
     46       {
     47           minusOne();
     48           m_pCountPtr = new CCountPtr<T>(pPoint);
     49       }
     50       void swap(CSmartPtr &x)
     51       {
     52           T *pRet = m_pCountPtr->m_pPoint;
     53           int count = m_pCountPtr->m_count;
     54 
     55           m_pCountPtr->m_pPoint = x.m_pCountPtr->m_pPoint;
     56           m_pCountPtr->m_count = x.m_pCountPtr->m_count;
     57 
     58           x.m_pCountPtr->m_pPoint = pRet;
     59           x.m_pCountPtr->m_count = count;
     60       }
     61 
     62       int user_count(){return m_pCountPtr->m_count; }
     63 
     64       T& operator *()
     65       {
     66           return *(m_pCountPtr->m_pT);
     67       }
     68 
     69       T* operator ->()
     70       {
     71           return m_pCountPtr->m_pT;
     72       }
     73 
     74     private:
     75       void minusOne()
     76       {
     77           if (m_pCountPtr->m_count-- == 0)
     78           {
     79               delete m_pCountPtr;
     80               m_pCountPtr = nullptr;
     81           }
     82           else
     83           {
     84               cout << "引用次数:" << m_pCountPtr->m_count << endl;
     85           }
     86       }
     87       CCountPtr<T> *m_pCountPtr;
     88 };
     89 
     90 /*这里使用了参数包,我对此不是很熟悉,直接copy的代码*/
     91 template<typename T, typename... Args>
     92 inline CSmartPtr<T>
     93 make_smart(Args&&... args)
     94 {
     95     return CSmartPtr<T>(new T(std::forward<Args>(args)...));
     96 }
     97 
     98 int main()
     99 {
    100     int b=10;
    101     int* a=&b;
    102     {
    103         CSmartPtr<int> sptr1(a);
    104         {
    105             cout << "*sptr1: " << *sptr1 << endl;
    106             CSmartPtr<int> sptr2 = sptr1;
    107 
    108             cout << "*sptr2: " << *sptr2 << endl;
    109 
    110             CSmartPtr<int> sptr3 = make_smart<int>(20);
    111             cout << "*sptr3: " << *sptr3 << endl;
    112         }
    113         cout<<"sptr1.count: "<< sptr1.user_count()<<endl;
    114     }
    115 
    116     system("pause");
    117     return 0;
    118 }

    以上为智能指针shared_ptr的实现过程,还是有很多东西要学习的。

    以下为参考网站,以至于很多东西都是直接拿过来的,感谢!

    https://www.cnblogs.com/QG-whz/p/4777312.html

     http://www.cplusplus.com/reference/memory/unique_ptr/unique_ptr/

    https://liam.page/2018/01/13/smart-pointer/

  • 相关阅读:
    QQ空间留言的JS
    Session超时问题(AOP 过滤器)
    IFrame实现的无刷新(仿ajax效果)...
    NPOI帮助类(Excel转DataTable、DataTable转Excel)
    SignalR with ASP.NET MVC5 可用于倒计时同步
    我(webabcd)的文章索引
    WorkFlow4.0--入门到精通系列-专题索引
    Android利用Fiddler进行网络数据抓包
    IIS给网站地址配置成HTTPS的
    SQL SERVER 2005 获取表的所有索引信息以及删除和新建语句
  • 原文地址:https://www.cnblogs.com/whutao/p/10623539.html
Copyright © 2020-2023  润新知