码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • std::weak_ptr(分析、仿写)


    目录

    一、为什么会有weak_ptr?

    1、看一个例子

    2.weak_ptr 是什么?

    3.weak_ ptr 如何使用?

    1、如何创建weak_ ptr 实例

     2、如何判断weak_ptr指向的对象是否存在

     3、weak_ptr的使用

     二、仿写std::weak_ptr

    1、c++参考手册

     2、代码


    一、为什么会有weak_ptr?

    1、看一个例子

    1. class Child;
    2. class Parent {
    3. public:
    4. shared_ptr _child;
    5. ~Parent() {
    6. cout << " Destroy Parent" << endl;
    7. }
    8. void hi()const {
    9. cout << "hello" << endl;
    10. }
    11. };
    12. class Child {
    13. public:
    14. shared_ptr parent;
    15. ~Child() {
    16. cout << " Bey child" << endl;
    17. }
    18. };
    19. int main() {
    20. shared_ptrpar = make_shared();
    21. shared_ptrpch = make_shared();
    22. par->_child = pch;
    23. pch->parent = par;
    24. pch->parent->hi();
    25. return 0;
    26. }

     到最后还是没有完成析构。 

    上面代码的运行结果,只打印出”Hello",而并没有打印出"Bye Parent"或"Bye Child",说明Parent和Child的析构函数并没有调用到。这是因为Parent和Child对象内部,具有各自指向对方的shared _ptr,加上parent和child这两个shared_ptr, 说明每个对象的引用计数都是2。当程序退出时,即使parent和child被销毁,也仅仅是导致引用计数变为了1,因此并未销毁Parent和Child对象。

    为了解决类似这样的问题,C++11 引入了weak_ptr,来打破这种循环引用。

    2.weak_ptr 是什么?

    weak ptr是为了配合shared _ptr 而引入的一种智能指针,它指向一个由shared_ptr 管理的对象而不影响所指对象的生命周期,也就是将一个weak_ptr 绑定到一个shared_ptr不会改变shared_ptr 的引用计数。不论是否有weak_ptr 指向,一旦最后一个指向对象的shared_ptr 被销毁,对象就会被释放。从这个角度看,weak_ptr 更像是shared_ptr 的一个助手而不是智能指针。weak_ptr并不拥有对动态对象的管辖权,weak_ptr 指向shared_ptr 的目标也不会增加计数器的值,相反,weak_ptr 拥有一套不纳入计数器的指针系统。

    3.weak_ ptr 如何使用?

    接下来,我们来看看weak_ptr的简单用法。

    1、如何创建weak_ ptr 实例

    当我们创建一个weak_ptr 时,需要用一个shared_ptr实例来初始化weak_ptr,由于是弱共享, weak_ ptr的创建并不会影响shared_ptr 的引用计数值。
    示例:

     2、如何判断weak_ptr指向的对象是否存在

    既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数,那就可能存在weak_ptr指向的对象被释放掉这种情况。这时,我们就不能使用weak_ptr直接的访问对象。那么如何判断weak_ptr指向的对象存在呢?

    c++提供lock函数来实现该功能。

    如果对象存在,lock()函数返回一个指向共享对象的shared_ptr,否则返回一个空shared_ptr。

    1. class Object {
    2. private:
    3. int value;
    4. public:
    5. Object(int x = 0) :value(x) { cout << "Object Create" << endl;; }
    6. ~Object() { cout << "Object Destroy"<
    7. int GetValue()const {
    8. return value;
    9. }
    10. };
    11. int main() {
    12. shared_ptrsp(new Object(10));
    13. weak_ptrwp(sp);
    14. if (shared_ptrpa = wp.lock()) {
    15. cout << pa->GetValue() << endl;
    16. }
    17. else {
    18. cout << wp.expired() << endl;//判断对象是否被销毁
    19. cout << "wp 引用对象为空" << endl;
    20. }
    21. return 0;
    22. }
    23.  3、weak_ptr的使用

      weak_ptr没有重载operator->和operator *操作符号,无法访问对象,可以使用lock()访问原始对象;

      1. class Child;
      2. class Parent {
      3. public:
      4. weak_ptr _child;
      5. ~Parent() {
      6. cout << " Destroy Parent" << endl;
      7. }
      8. void hi()const {
      9. cout << "hello" << endl;
      10. }
      11. };
      12. class Child {
      13. public:
      14. weak_ptr parent;
      15. ~Child() {
      16. cout << " Bey child" << endl;
      17. }
      18. };
      19. int main() {
      20. shared_ptrpar = make_shared();
      21. shared_ptrpch = make_shared();
      22. par->_child = pch;
      23. pch->parent = par;
      24. if (!(pch->parent.expired())) {
      25. pch->parent.lock()->hi();
      26. }
      27. return 0;
      28. }

       

       二、仿写std::weak_ptr

      1、c++参考手册

       2、代码

      1. #ifndef MY_WEAK_PTR
      2. #define MY_WEAK_PTR
      3. #include
      4. template<class _Ty>
      5. class MyDeletor
      6. {
      7. public:
      8. MyDeletor() {}
      9. void operator() {_Ty* ptr}const
      10. {
      11. if (ptr != nullptr)
      12. {
      13. delete ptr;
      14. }
      15. }
      16. };
      17. template<class _Ty>
      18. class MyDeletor<_Ty[]>
      19. {
      20. public:
      21. MyDeletor() = default;
      22. void operator() { _Ty* ptr }const
      23. {
      24. if (ptr != nullptr)
      25. {
      26. delete []ptr;
      27. }
      28. }
      29. };
      30. template <class _Ty>
      31. class RefCnt
      32. {
      33. public:
      34. _Ty* _Ptr;
      35. std::atomic_int _Uses;
      36. std::atomic_int _Weaks;
      37. public:
      38. RefCnt(_Ty* p) :_Ptr(p), _Uses(1), _Weaks(1) {}
      39. ~RefCnt() {}
      40. void _Incref() { _Uses += 1; }
      41. void _Incwref() { _Weaks += 1; }
      42. };
      43. template<class _Ty,class _Dx=MyDeletor<_Ty>>
      44. class my_shared_ptr
      45. {
      46. private:
      47. _Ty* _Ptr;
      48. RefCnt<_Ty>* _Rep;
      49. _Dx _mDeletor;
      50. public:
      51. my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
      52. {
      53. if (p != nullptr)
      54. {
      55. _Ptr = p;
      56. _Rep = new RefCnt<_Ty>(p);
      57. }
      58. }
      59. my_shared_ptr(const my_shared_ptr& _Y) :_Ptr(_Y._Ptr), _Rep(_Y._Rep)
      60. {
      61. if (_Rep != nullptr)
      62. {
      63. _Rep->_Incref();
      64. }
      65. }
      66. my_shared_ptr(my_shared_ptr&& other):_Ptr(other._Ptr),_Rep(other._Rep)
      67. {
      68. other._Ptr = nullptr;
      69. other._Rep = nullptr;
      70. }
      71. my_shared_ptr& operator =(const my_shared_ptr& r)
      72. {
      73. if (this == &r || this->_Ptr == r._Ptr)return *this;
      74. if (_Ptr != nullptr && --_Rep->_Uses == 0)
      75. {
      76. _mDeletor(_Ptr);
      77. if (--_Rep->_Weaks == 0)
      78. {
      79. delete _Rep;
      80. }
      81. }
      82. _Ptr = r._Ptr;
      83. _Rep = r._Rep;
      84. if (_Ptr != nullptr)
      85. {
      86. _Rep->_Incref();
      87. }
      88. return *this;
      89. }
      90. my_shared_ptr& operator =(my_shared_ptr&& other)
      91. {
      92. if (this == &other)return *this;
      93. if (this->_Ptr != nullptr && other->_Ptr != nullptr && _Ptr == other->_Ptr)
      94. {
      95. this->_Rep->_Uses -= 1;
      96. other->_Ptr = nullptr;
      97. other->_Rep = nullptr;
      98. return *this;
      99. }
      100. if (_Ptr != nullptr && --_Rep->_Uses == 0)
      101. {
      102. _mDeletor(_Ptr);
      103. if (--_Rep->_Weaks == 0)
      104. {
      105. delete _Rep;
      106. }
      107. }
      108. _Ptr = other._Ptr;
      109. _Rep = other._Rep;
      110. other._Ptr = nullptr;
      111. other._Rep = nullptr;
      112. return *this;
      113. }
      114. ~my_shared_ptr()
      115. {
      116. if (_Rep != nullptr && --_Rep->_Uses == 0)
      117. {
      118. _mDeletor(_Ptr);
      119. if (--_Rep->_Weaks == 0)
      120. {
      121. delete _Rep;
      122. }
      123. }
      124. _Ptr = nullptr;
      125. _Rep = nullptr;
      126. }
      127. _Ty* get()const { return _Ptr; }
      128. _Ty& operator*()const { return *get(); }
      129. _Ty* operator ->() const { return get(); }
      130. size_t use_count()const
      131. {
      132. if (_Rep == nullptr)return 0;
      133. return _Rep->_Uses;
      134. }
      135. void swap(my_shared_ptr& r)
      136. {
      137. std::swap(_Ptr, r._Ptr);
      138. std::swap(_Rep, r._Rep);
      139. }
      140. operator bool()const { return _Ptr != nullptr; }
      141. };
      142. template <class _Ty>
      143. class my_weak_ptr
      144. {
      145. private:
      146. RefCnt<_Ty>* _Rep;
      147. public:
      148. my_weak_ptr() :_Rep(nullptr) {}
      149. my_weak_ptr(const my_weak_ptr<_Ty>& other) :_Rep(other._Rep)
      150. {
      151. if (_Rep != nullptr)
      152. {
      153. _Rep->_Incwref();
      154. }
      155. }
      156. my_weak_ptr(const my_weak_ptr& other) :_Rep(other._Rep)
      157. {
      158. if (_Rep != nullptr)
      159. {
      160. _Rep->_Incwref();
      161. }
      162. }
      163. my_weak_ptr(my_weak_ptr&& other) :_Rep(other._Rep)
      164. {
      165. other._Rep = nullptr;
      166. }
      167. my_weak_ptr& operator =(const my_weak_ptr& other)
      168. {
      169. if (this == &other || this->_Rep == other._Rep)return *this;
      170. if (this->_Rep != nullptr && --_Rep->_Weaks == 0)
      171. {
      172. delete _Rep;
      173. }
      174. _Rep = other->_Rep;
      175. if (_Rep != nullptr)
      176. {
      177. _Rep->_Incwref();
      178. }
      179. return *this;
      180. }
      181. my_weak_ptr& operator=(my_weak_ptr&& other)
      182. {
      183. if (this == &other)return *this;
      184. if (this->_Rep != nullptr && other._Rep != nullptr && _Rep == other._Rep)
      185. {
      186. this->_Rep->_Weaks -= 1;
      187. other._Rep = nullptr;
      188. return *this;
      189. }
      190. if (_Rep != nullptr && --_Rep->_Weaks == 0)
      191. {
      192. delete _Rep;
      193. }
      194. _Rep = other._Rep;
      195. other._Rep = nullptr;
      196. return *this;
      197. }
      198. my_weak_ptr& operator(const my_shared_ptr<_Ty>& other)
      199. {
      200. if (_Rep != nullptr && --_Rep->Weaks == 0)
      201. {
      202. delete _Rep;
      203. }
      204. _Rep = other->_Rep;
      205. if (_Rep != nullptr)
      206. {
      207. _Rep->Incwref();
      208. }
      209. return *this;
      210. }
      211. my_weak_ptr& operator =(my_shared_ptr<_Ty>&& other) = delete;
      212. ~my_weak_ptr()
      213. {
      214. if (_Rep != nullptr && --_Rep->_Weaks == 0)
      215. {
      216. delete _Rep;
      217. }
      218. _Rep = nullptr;
      219. }
      220. bool expired()const
      221. {
      222. return this->_Rep->_Uses == 0;
      223. }
      224. my_shared_ptr<_Ty>lock()const
      225. {
      226. my_shared_ptr<_Ty>_Ret;
      227. _Ret._Ptr = _Rep->_Ptr;
      228. _Ret._Rep = _Rep;
      229. _Ret._Rep->_Incref;
      230. }
      231. };
      232. #endif

    24. 相关阅读:
      Linux上单机部署RocketMq
      C++核心编程:P8->类和对象----运算符重载
      Kotlin高仿微信-第57篇-VIP管理列表
      owasp top 10
      jQuery之Callbacks函数功能测试
      前端笔记(11) Vue3 Router 编程式导航 router.push router.replace
      Ubuntu 20.04.05安装ceres-1.14.0
      吴恩达机器学习笔记:第 8 周-13 聚类(Clustering)13.1-13.2
      LeetCode 热题 HOT 100:回溯专题
      redis试题按知识点归类
    25. 原文地址:https://blog.csdn.net/weixin_48560325/article/details/128052961
      • 最新文章
      • 攻防演习之三天拿下官网站群
        数据安全治理学习——前期安全规划和安全管理体系建设
        企业安全 | 企业内一次钓鱼演练准备过程
        内网渗透测试 | Kerberos协议及其部分攻击手法
        0day的产生 | 不懂代码的"代码审计"
        安装scrcpy-client模块av模块异常,环境问题解决方案
        leetcode hot100【LeetCode 279. 完全平方数】java实现
        OpenWrt下安装Mosquitto
        AnatoMask论文汇总
        【AI日记】24.11.01 LangChain、openai api和github copilot
      • 热门文章
      • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
        奉劝各位学弟学妹们,该打造你的技术影响力了!
        五年了,我在 CSDN 的两个一百万。
        Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
        面试官都震惊,你这网络基础可以啊!
        你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
        心情不好的时候,用 Python 画棵樱花树送给自己吧
        通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
        13 万字 C 语言从入门到精通保姆级教程2021 年版
        10行代码集2000张美女图,Python爬虫120例,再上征途
      Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
      正则表达式工具 cron表达式工具 密码生成工具

      京公网安备 11010502049817号