C++——智能指针shared_ptr的实现
- 起初,我最直观的设计想法,直接设计一个类:包含全部要素(对象,指针计数)。然后提供出去。
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/