std::shared_ptr 是通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可占有同一对象大概实现了一下,主要实现原理为,共享指针内部持有堆资源

的指针以及引用计数的指针,通过对这两个指针的维护,达到多个共享对象对同一资源的控制

 

  实现主要分为三个文件。share_ptr.h,smart_ptr_define.h, main.cpp  (编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

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

  主要实现文件share_ptr.h

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

  main函数测试

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

  测试最后打印:

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

  shared_ptr主要需实现的功能点如下(以下总结引用自网络,非原创):

  1. 没有参数构造的时候,初始化为空,即对象和引用计数的两个指针都为0

  2. 使用指针为参数构造时,拥有此指针,在没有智能指针指向它时进行析构

  3. 智能指针复制时,两个智能指针共同拥有内部指针,引用计数同时+1

  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机制

 

版权声明:本文为blog-yejy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/blog-yejy/p/9030722.html