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/

转载于:https://www.cnblogs.com/whutao/p/10623539.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值