当前位置:   article > 正文

智能指针派生类—shared_ptr(STL源码)_shared_ptr 派生类和基类

shared_ptr 派生类和基类
  1. // shared_ptr虽然能和其他shared_ptr共享同一内存,但是千万不能通过原始指针持有一个即将过期的指针,即2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次情形如下:
  2. std::shared_ptr<int> p= std::make_shared<int>(1);
  3. {
  4. std::unique_ptr<int> q(new int(111111));// q也可以是shared_ptr
  5. p.reset(qw.get());// p会释放掉指向'std::make_shared<int>(1)'的内存,转而控制'new int(111111)'内存,但是却和q同时共享同一内存,但是q是临时变量,在{}执行完后释放内存,导致p成为悬空指针,后续在p析构时会重新再delete这块内存,导致重复释放出错
  6. }
  7. 所以使用第三行reset语句的前提是你确保q放弃对其资源的控制,如q.release();
  8. 以上情形同时适用于unique_ptr
  9. 处于以上情况,c++11出了一种新特性为enable_shared_from_this类用于解决上述返回共同管理的指针的解决方案
  10. // TEMPLATE CLASS shared_ptr
  11. // shared_ptr智能指针类模板
  12. template<class _Ty>
  13. class shared_ptr
  14. : public _Ptr_base<_Ty> // 继承自智能指针基类
  15. { // class for reference counted resource management 引用计数资源管理类
  16. public:
  17. typedef shared_ptr<_Ty> _Myt; // 定义自身 类型
  18. typedef _Ptr_base<_Ty> _Mybase; // 定义基类 类型
  19. //
  20. // 构造函数
  21. shared_ptr() _NOEXCEPT
  22. { // construct empty shared_ptr
  23. }
  24. // 允许从原始指针_Px显式构造
  25. template<class _Ux>
  26. explicit shared_ptr(_Ux *_Px)
  27. { // construct shared_ptr object that owns _Px
  28. _Resetp(_Px);
  29. }
  30. // 参数2为 删除器类型(删除资源数据)
  31. template<class _Ux,
  32. class _Dx>
  33. shared_ptr(_Ux *_Px, _Dx _Dt)
  34. { // construct with _Px, deleter
  35. _Resetp(_Px, _Dt);
  36. }
  37. shared_ptr(nullptr_t)
  38. { // construct empty shared_ptr
  39. }
  40. template<class _Dx>
  41. shared_ptr(nullptr_t, _Dx _Dt)
  42. { // construct with nullptr, deleter
  43. _Resetp((_Ty *)0, _Dt);
  44. }
  45. // 参数3:分配器类型(销毁计数器对象)
  46. template<class _Dx,
  47. class _Alloc>
  48. shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax)
  49. { // construct with nullptr, deleter, allocator
  50. _Resetp((_Ty *)0, _Dt, _Ax);
  51. }
  52. template<class _Ux,
  53. class _Dx,
  54. class _Alloc>
  55. shared_ptr(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
  56. { // construct with _Px, deleter, allocator
  57. _Resetp(_Px, _Dt, _Ax);
  58. }
  59. // 从其他智能指针构造(调用基类的_Reset)
  60. template<class _Ty2>
  61. shared_ptr(const shared_ptr<_Ty2>& _Right, _Ty *_Px) _NOEXCEPT
  62. { // construct shared_ptr object that aliases _Right
  63. this->_Reset(_Px, _Right);
  64. }
  65. // copy构造函数
  66. shared_ptr(const _Myt& _Other) _NOEXCEPT
  67. { // construct shared_ptr object that owns same resource as _Other
  68. this->_Reset(_Other);
  69. }
  70. // enable_if的第一个参数(is_convertible<_Ty2 *, _Ty *>::value)为true时,才会内部定义type(第二个参数,这为void),否则无法通过编译
  71. // is_convertible<_Ty2 *, _Ty *>:判断是否可以被转化 第一个参数的类型 可以转化为第二个参数的类型
  72. // 例如对于类:如果A是基类,B是子类,那么B可以转化为A,也就是B是一种A;用is_convertible表示如下:
  73. // std::cout << std::boolalpha;   //输出格式调整,0false,非0true
  74. // std::is_convertible<B, A>::value << endl;// 判断B是否可以转化为A,并返回true or false
  75. template<class _Ty2,
  76. class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
  77. void>::type>
  78. shared_ptr(const shared_ptr<_Ty2>& _Other) _NOEXCEPT
  79. { // construct shared_ptr object that owns same resource as _Other
  80. this->_Reset(_Other);
  81. }
  82. template<class _Ty2>
  83. explicit shared_ptr(const weak_ptr<_Ty2>& _Other,
  84. bool _Throw = true)
  85. { // construct shared_ptr object that owns resource *_Other
  86. this->_Reset(_Other, _Throw);
  87. }
  88. // 从auto_ptr指针,移动构造函数
  89. template<class _Ty2>
  90. shared_ptr(auto_ptr<_Ty2>&& _Other)
  91. { // construct shared_ptr object that owns *_Other.get()
  92. this->_Reset(_STD move(_Other));// move(左值)转为右值引用,调用基类void _Reset(auto_ptr<_Ty2>&& _Other)
  93. }
  94. // 类型转换
  95. template<class _Ty2>
  96. shared_ptr(const shared_ptr<_Ty2>& _Other, const _Static_tag& _Tag)
  97. { // construct shared_ptr object for static_pointer_cast
  98. this->_Reset(_Other, _Tag);
  99. }
  100. template<class _Ty2>
  101. shared_ptr(const shared_ptr<_Ty2>& _Other, const _Const_tag& _Tag)
  102. { // construct shared_ptr object for const_pointer_cast
  103. this->_Reset(_Other, _Tag);
  104. }
  105. template<class _Ty2>
  106. shared_ptr(const shared_ptr<_Ty2>& _Other, const _Dynamic_tag& _Tag)
  107. { // construct shared_ptr object for dynamic_pointer_cast
  108. this->_Reset(_Other, _Tag);
  109. }
  110. // 从shared_ptr指针,移动构造函数
  111. shared_ptr(_Myt&& _Right) _NOEXCEPT
  112. : _Mybase(_STD forward<_Myt>(_Right))// 转发右值引用属性(完全依照模板的参数的类型)
  113. { // construct shared_ptr object that takes resource from _Right
  114. }
  115. template<class _Ty2,
  116. class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
  117. void>::type>
  118. shared_ptr(shared_ptr<_Ty2>&& _Right) _NOEXCEPT
  119. : _Mybase(_STD forward<shared_ptr<_Ty2> >(_Right))
  120. { // construct shared_ptr object that takes resource from _Right
  121. }
  122. // 从unique_ptr指针,移动构造函数
  123. template<class _Ux,
  124. class _Dx>
  125. shared_ptr(unique_ptr<_Ux, _Dx>&& _Right)
  126. { // construct from unique_ptr
  127. _Resetp(_Right.release(), _Right.get_deleter());// 转移_Right的指针控制权给this,_Right为空
  128. }
  129. //赋值移动构造函数
  130. template<class _Ux,
  131. class _Dx>
  132. _Myt& operator=(unique_ptr<_Ux, _Dx>&& _Right)
  133. { // move from unique_ptr
  134. shared_ptr(_STD move(_Right)).swap(*this);
  135. return (*this);
  136. }
  137. _Myt& operator=(_Myt&& _Right) _NOEXCEPT
  138. { // construct shared_ptr object that takes resource from _Right
  139. shared_ptr(_STD move(_Right)).swap(*this);
  140. return (*this);
  141. }
  142. template<class _Ty2>
  143. _Myt& operator=(shared_ptr<_Ty2>&& _Right) _NOEXCEPT
  144. { // construct shared_ptr object that takes resource from _Right
  145. shared_ptr(_STD move(_Right)).swap(*this);
  146. return (*this);
  147. }
  148. // 析构,引用计数-1
  149. ~shared_ptr() _NOEXCEPT
  150. { // release resource
  151. this->_Decref();
  152. }
  153. //赋值copy构造函数
  154. _Myt& operator=(const _Myt& _Right) _NOEXCEPT
  155. { // assign shared ownership of resource owned by _Right
  156. shared_ptr(_Right).swap(*this);// shared_ptr(_Right)临时对象先递增右值的引用计数,swap交换后临时对象指向左值,即this指向了引用计数已经增1后的右值(即_Right)了,左值从之前的this指向它,编程临时对象指向它,所以到这一步时,之前左值的计数不变,等到{}代码结束后,临时对象释放,调用析构,引用计数-1,所以从代码层面印证了 =右边计数+1,左边计数-1
  157. return (*this);
  158. }
  159. template<class _Ty2>
  160. _Myt& operator=(const shared_ptr<_Ty2>& _Right) _NOEXCEPT
  161. { // assign shared ownership of resource owned by _Right
  162. shared_ptr(_Right).swap(*this);
  163. return (*this);
  164. }
  165. template<class _Ty2>
  166. _Myt& operator=(auto_ptr<_Ty2>&& _Right)
  167. { // assign ownership of resource pointed to by _Right
  168. shared_ptr(_STD move(_Right)).swap(*this);
  169. return (*this);
  170. }
  171. // 释放资源,或重新指向_Px
  172. // 释放资源并转换为空的shared_ptr对象
  173. void reset() _NOEXCEPT
  174. { // release resource and convert to empty shared_ptr object
  175. shared_ptr().swap(*this);// 临时无名对象 和 当前对象 交换,然后无名对象在函数执行完后析构,释放资源
  176. }
  177. template<class _Ux>
  178. void reset(_Ux *_Px)
  179. { // release, take ownership of _Px
  180. shared_ptr(_Px).swap(*this);
  181. }
  182. template<class _Ux,
  183. class _Dx>
  184. void reset(_Ux *_Px, _Dx _Dt)
  185. { // release, take ownership of _Px, with deleter _Dt
  186. shared_ptr(_Px, _Dt).swap(*this);
  187. }
  188. template<class _Ux,
  189. class _Dx,
  190. class _Alloc>
  191. void reset(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
  192. { // release, take ownership of _Px, with deleter _Dt, allocator _Ax
  193. shared_ptr(_Px, _Dt, _Ax).swap(*this);
  194. }
  195. void swap(_Myt& _Other) _NOEXCEPT
  196. { // swap pointers
  197. this->_Swap(_Other);
  198. }
  199. // 得到原始数据指针
  200. _Ty *get() const _NOEXCEPT
  201. { // return pointer to resource
  202. return (this->_Get());
  203. }
  204. // 数据的引用(重载解地址运算符*)
  205. typename add_reference<_Ty>::type operator*() const _NOEXCEPT
  206. { // return reference to resource
  207. return (*this->_Get());
  208. }
  209. // 得到原始数据指针(重载指针访问运算符->)
  210. _Ty *operator->() const _NOEXCEPT
  211. { // return pointer to resource
  212. return (this->_Get());
  213. }
  214. // 是否计数为1
  215. bool unique() const _NOEXCEPT
  216. { // return true if no other shared_ptr object owns this resource
  217. return (this->use_count() == 1);
  218. }
  219. // 本类型到bool的转换,不允许使用参数,即if(!shared_ptr)时调用
  220. explicit operator bool() const _NOEXCEPT
  221. { // test if shared_ptr object owns no resource
  222. return (this->_Get() != 0);
  223. }
  224. private:
  225. // 内部构造时调用_Resetp
  226. template<class _Ux>
  227. void _Resetp(_Ux *_Px)
  228. { // release, take ownership of _Px
  229. _TRY_BEGIN // allocate control block and reset
  230. _Resetp0(_Px, new _Ref_count<_Ux>(_Px));
  231. _CATCH_ALL // allocation failed, delete resource
  232. delete _Px;
  233. _RERAISE;
  234. _CATCH_END
  235. }
  236. template<class _Ux,
  237. class _Dx>
  238. void _Resetp(_Ux *_Px, _Dx _Dt)
  239. { // release, take ownership of _Px, deleter _Dt
  240. _TRY_BEGIN // allocate control block and reset
  241. _Resetp0(_Px, new _Ref_count_del<_Ux, _Dx>(_Px, _Dt));// 资源_Px同时交给两方管理,一处为智能指针的基类(_Ref_count_del)的成员_Ty *_Ptr;另一处为成员_Ref_count_base *_Rep(本身为计数基类)的派生类对象(这里为_Ref_count_del)的新成员_Ty * _Ptr;
  242. _CATCH_ALL // allocation failed, delete resource
  243. _Dt(_Px);
  244. _RERAISE;
  245. _CATCH_END
  246. }
  247. template<class _Ux,
  248. class _Dx,
  249. class _Alloc>
  250. void _Resetp(_Ux *_Px, _Dx _Dt, _Alloc _Ax)
  251. { // release, take ownership of _Px, deleter _Dt, allocator _Ax
  252. typedef _Ref_count_del_alloc<_Ux, _Dx, _Alloc> _Refd;
  253. typename _Alloc::template rebind<_Refd>::other _Al = _Ax;
  254. _TRY_BEGIN // allocate control block and reset
  255. _Refd *_Ptr = _Al.allocate(1);
  256. ::new (_Ptr)_Refd(_Px, _Dt, _Al);
  257. _Resetp0(_Px, _Ptr);
  258. _CATCH_ALL // allocation failed, delete resource
  259. _Dt(_Px);
  260. _RERAISE;
  261. _CATCH_END
  262. }
  263. public:
  264. template<class _Ux>
  265. void _Resetp0(_Ux *_Px, _Ref_count_base *_Rx)
  266. { // release resource and take ownership of _Px
  267. this->_Reset0(_Px, _Rx);
  268. _Enable_shared(_Px, _Rx); // 管理指向同一内存的指针,管理的类需继承enable_shared_from_this
  269. }
  270. };
  271. // _Resetp0(_Px, new _Ref_count_del<_Ux, _Dx>(_Px, _Dt));
  272. // 由此可见,资源由子对象_Ref_count_base的派生类对象指针_Rep管理,
  273. // 1.当智能指针.reset()时,当前指针(含资源,引用计数n)与临时无名对象指针(没有资源,引用计数0)交换,临时无名对象(此时有资源且引用计数为n)在函数执行完后会析构;减少引用计数,
  274. // 2.当多个指向a同一引用的智能指针放弃自己的控制权时(如.reset()或 = otherPtr时,指向a的引用计数减少)
  275. // 上述两种情况 当引用计数减少,直至0时,_Rep(派生类)会调用自己的纯虚函数_Destroy();_Decwref();从而释放资源
  276. /非成员函数,重载操作符,用于两智能指针间的比较(只列举几个)/
  277. // 重载==,判断两个智能指针是否管理同一个资源
  278. template<class _Ty1,
  279. class _Ty2>
  280. bool operator==(const shared_ptr<_Ty1>& _Left,
  281. const shared_ptr<_Ty2>& _Right) _NOEXCEPT
  282. { // test if shared_ptr == shared_ptr
  283. return (_Left.get() == _Right.get());
  284. }
  285. // 重载!=,判断两个智能指针是否管理不同一个资源
  286. template<class _Ty1,
  287. class _Ty2>
  288. bool operator!=(const shared_ptr<_Ty1>& _Left,
  289. const shared_ptr<_Ty2>& _Right) _NOEXCEPT
  290. { // test if shared_ptr != shared_ptr
  291. return (!(_Left == _Right));// 调用operator==
  292. }
  293. // 重载<,判断参数1智能指针管理的资源地址是否小于参数2
  294. template<class _Ty1,
  295. class _Ty2>
  296. bool operator<(const shared_ptr<_Ty1>& _Left,
  297. const shared_ptr<_Ty2>& _Right) _NOEXCEPT
  298. { // test if shared_ptr < shared_ptr
  299. return (less<decltype(_Always_false<_Ty1>::value// less的模板参数为_Right.get()的类型,因为_Always_false<_Ty1>::valuefalse
  300. ? _Left.get() : _Right.get())>()(
  301. _Left.get(), _Right.get()));
  302. }
  303. // 重载>=,判断参数1智能指针管理的资源地址是否不小于参数2
  304. template<class _Ty1,
  305. class _Ty2>
  306. bool operator>=(const shared_ptr<_Ty1>& _Left,
  307. const shared_ptr<_Ty2>& _Right) _NOEXCEPT
  308. { // shared_ptr >= shared_ptr
  309. return (!(_Left < _Right));
  310. }
  311. // 其余比较函数类似
  312. // 上述比较函数为普通非成员模板函数,但是因为是两指针之间的比较,可以在类内实现,成为单参数的成员函数(p1 < p2,即调用p1.operator<(p2));
  313. /非成员函数,重载操作符,用于智能指针和空指针间的比较(只列举几个)/
  314. // 重载==,判断_Left智能指针管理的资源地址是否为0(没管理任何内存),if(_Left == 0)时调用,==后必须0,非0报编译错误
  315. template<class _Ty>
  316. bool operator==(const shared_ptr<_Ty>& _Left,
  317. nullptr_t) _NOEXCEPT
  318. { // test if shared_ptr == nullptr
  319. return (_Left.get() == (_Ty *)0);
  320. }
  321. // 重载==,和上述区别为if(0 == _Left)时调用,==前必须0,非0报编译错误
  322. template<class _Ty>
  323. bool operator==(nullptr_t,
  324. const shared_ptr<_Ty>& _Right) _NOEXCEPT
  325. { // test if nullptr == shared_ptr
  326. return ((_Ty *)0 == _Right.get());
  327. }
  328. // 必须和0(nullptr_t)比较,包括其他未举的例子
  329. // 当参数为nullptr_t时,就不能写成成员模板函数了,只能写成普通模板函数,因为对于每个操作符都有两个重载函数,例如上述
  330. // 对于==操作符的重载有两个(参数1,2互换位置),之所以这个写,是因为当有语句if(p == 0)或if (0 == p)是,都能正常调用上述两个函数。
  331. // 而写成成员函数时,if(p == 0)可以正常调用bool operator==(nullptr_t),被解释为p.operator==(0),但是当if(0 == p ),解释为0.operator==(p)显然是不对的。
  332. // TEMPLATE FUNCTION make_shared
  333. template<class _Ty,class... _Types>
  334. inline shared_ptr<_Ty> make_shared(_Types&&... _Args)
  335. { // make a shared_ptr
  336. _Ref_count_obj<_Ty> *_Rx = new _Ref_count_obj<_Ty>(_STD forward<_Types>(_Args)...);
  337. shared_ptr<_Ty> _Ret;
  338. _Ret._Resetp0(_Rx->_Getptr(), _Rx);
  339. return (_Ret);
  340. }
  341. // std::shared_ptr<int> p = std::make_shared<int>(1);

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/206282
推荐阅读
相关标签
  

闽ICP备14008679号