智能指針之 shared_ptr

   std::shared_ptr 是經過指針保持對象共享全部權的智能指針。多個 shared_ptr 對象可佔有同一對象大概實現了一下,主要實現原理爲,共享指針內部持有堆資源的指針以及引用計數的指針,經過對這兩個指針的維護,達到多個共享對象對同一資源的控制ios

  實現主要分爲三個文件。share_ptr.h,smart_ptr_define.h, main.cpp  (編譯平臺:Linux centos 7.0 編譯器:gcc 4.8.5 )centos

 1 //smart_ptr_define.h
 2 #ifndef __SMART_PTR_DEFINE_H__
 3 #define __SMART_PTR_DEFINE_H__
 4 
 5 #include <assert.h>
 6 
 7 #define PTR_ASSERT(x) assert(x)
 8 
 9 #define _SMART_PTR_BEGIN    namespace smartptr {
10 #define _SMART_PTR_END        }
11 #define _SMART_PTR    ::smartptr::
12 
13 #endif

  主要實現文件share_ptr.h網絡

  1 #ifndef __SHARE_PTR_H__
  2 #define __SHARE_PTR_H__
  3 
  4 #include <iostream>
  5 #include "smart_ptr_define.h"
  6 
  7 _SMART_PTR_BEGIN
  8 
  9 template <class T>
 10 struct default_deleter
 11 {
 12     void operator()(T* ptr)
 13     {
 14         if (ptr != NULL)
 15         {
 16             delete ptr;
 17             ptr = NULL;
 18         }
 19     }
 20 };
 21 
 22 template <class T, class deleter = default_deleter<T> >
 23 class shared_ptr
 24 {
 25 public:
 26     typedef shared_ptr<T, deleter> SHARE_PTR;
 27 
 28     shared_ptr()
 29     {
 30         m_ptr = NULL;
 31         m_iRefCount = NULL;
 32     }
 33 
 34     explicit shared_ptr(T* ptr)
 35     {
 36         if (ptr != NULL)
 37         {
 38             m_ptr = ptr;
 39             RefCountInit();
 40         }
 41     }
 42 
 43     shared_ptr(deleter d, T* ptr)
 44     {
 45         if (ptr != NULL)
 46         {
 47             m_ptr = ptr;
 48             m_deleter = d;
 49             RefCountInit();
 50         }
 51     }
 52 
 53     //拷貝構造
 54     shared_ptr(const SHARE_PTR& sh_ptr) 
 55     {
 56         if (sh_ptr.m_ptr != NULL)
 57         {
 58             m_ptr = sh_ptr.m_ptr;
 59             m_deleter = sh_ptr.m_deleter;
 60             m_iRefCount = sh_ptr.m_iRefCount;
 61 
 62             RefCountIncrease();
 63         }
 64     }
 65 
 66     //賦值運算符
 67     SHARE_PTR& operator = (const SHARE_PTR& sh_ptr)
 68     {
 69         if (this != &sh_ptr)
 70         {
 71             RefCountDecrease();
 72 
 73             if (sh_ptr.m_ptr != NULL)
 74             {
 75                 m_ptr = sh_ptr.m_ptr;
 76                 m_deleter = sh_ptr.m_deleter;
 77                 m_iRefCount = sh_ptr.m_iRefCount;
 78 
 79                 RefCountIncrease();
 80             }
 81         }
 82 
 83         return (*this);
 84     }
 85 
 86     ~shared_ptr()
 87     {
 88         RefCountDecrease();
 89     }
 90 
 91 public:
 92     //提領操做
 93     T& operator*()
 94     {
 95         PTR_ASSERT(m_ptr != NULL);
 96         return *(m_ptr);
 97     }
 98 
 99     //原始指針操做
100     T* operator->()
101     {
102         PTR_ASSERT(m_ptr != NULL);
103         return m_ptr;
104     }
105 
106     operator bool() const
107     {
108         return m_ptr != NULL;
109     }
110 
111     //取得原始指針
112     T* getPointer()
113     {
114         PTR_ASSERT(m_ptr != NULL);
115         return m_ptr;
116     }
117 
118     //得到引用計數
119     int getRefCount()
120     {
121         PTR_ASSERT(m_iRefCount != NULL);
122         return *m_iRefCount;
123     }
124 
125     
126 private:
127     void RefCountInit()
128     {
129         m_iRefCount = new int(1);
130     }
131 
132     void RefCountIncrease()
133     {
134         if (m_iRefCount != NULL)
135         {
136             ++(*m_iRefCount);
137         }
138     }
139 
140     void RefCountDecrease()
141     {
142         if (m_iRefCount != NULL && --(*m_iRefCount) == 0)
143         {
144             m_deleter(m_ptr);
145             delete m_iRefCount;
146             m_ptr = NULL;
147             m_iRefCount = NULL;
148         }
149     }
150 
151 private:
152     int* m_iRefCount; //引用計數
153 
154     T*  m_ptr; //對象指針
155 
156     deleter m_deleter; //刪除器
157 };
158 
159 _SMART_PTR_END
160 #endif // !__SHARE_PTR_H__

  main函數測試函數

 1 #include "share_ptr.h"
 2 #include <memory>
 3 
 4 class Test
 5 {
 6 public:
 7     Test()
 8     {
 9         std::cout << "construct.." << std::endl;
10     }
11 
12     void method()
13     {
14         std::cout << "welcome Test.." << std::endl;
15     }
16 
17     ~Test()
18     {
19         std::cout << "destruct.." << std::endl;
20     }
21 };
22 
23 int main()
24 {
25     Test* t1 = new Test();
26 
27     _SMART_PTR shared_ptr<Test> shptr(t1);
28 
29     _SMART_PTR shared_ptr<Test> shptr1(shptr);
30 
31     _SMART_PTR shared_ptr<Test> shptr2 = shptr1;
32 
33     std::cout << "RefCount: " << shptr2.getRefCount() << std::endl;
34 
35     shptr2->method();
36 
37     (*shptr2).method();
38 
39     if (shptr2)
40     {
41         std::cout << "ptr is exit " << std::endl;
42     }
43 
44 
45 
46     return 0;
47 }

  測試最後打印:測試

1 [yejy@yejy cmake-00]$ ./smartptr 
2 construct..
3 RefCount: 3
4 welcome Test..
5 welcome Test..
6 ptr is exit 
7 destruct..
8 [yejy@yejy cmake-00]$

  shared_ptr主要需實現的功能點以下(如下總結引用自網絡,非原創):this

  1. 沒有參數構造的時候,初始化爲空,即對象和引用計數的兩個指針都爲0spa

  2. 使用指針爲參數構造時,擁有此指針,在沒有智能指針指向它時進行析構指針

  3. 智能指針複製時,兩個智能指針共同擁有內部指針,引用計數同時+1code

  4. 智能指針可使用智能指針或普通指針從新賦值。重載=操做符,對於智能指針賦值,須要考慮是否自賦值,以免將自身析構了後再從新賦值,而普通指針賦值給智能指針,則不須要考慮自賦值,由於二者自己是兩個類型對象

  5. 得到底層指針的訪問,定義getPtrPointer()getPtrCounter()來分別返回底層指針和引用計數,定義operator bool()來處理智能指針隱式轉換爲bool的狀況

  6. 重載->×操做符 ,來實現與普通指針相同的指針訪問

  7. 須要支持隱式指針類型轉換,static_cast不支持而dynamic_cast支持的轉換則使用Cast<T2>()成員函數來解決。考慮定義友元類,以防止指向派生類的智能指針有權限訪問基類的內部對象;當轉型不成功時,返回爲空 (未實現)

  8. 若是一個裸指針直接用來建立兩個智能指針的話,指望的狀況是當兩個智能指針析構掉的時候,該指針會被delete兩次從而崩潰(這是shared_ptr的特色)

  9. 不處理循環引用(也是shared_ptr的特色),能夠經過與weak_ptr協做來打破循環

  10. 實現deleter機制

相關文章
相關標籤/搜索