当前位置:   article > 正文

weak_ptr 智能指针的使用_weakptr使用

weakptr使用

目录

一,weak_ptr 变量的定义

二,expired() 成员函数

三,lock() 成员函数

四,use_count() 成员函数

五,为什么要用 weak_ptr


一,weak_ptr 变量的定义

weak_ptr 对象的构造有3种方法:

1,构造空对象,如 std::weak_ptr<CTest> weakPtr;

2,拷贝构造,如 std::weak_ptr<CTest> weakPtr2(weakPtr);

3,用shared_ptr 对象进行初始化,如

std::shared_ptr<CTest> ptr = std::make_shared<CTest>();

std::weak_ptr<CTest> weakPtr3(ptr);

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory>
  4. class CTest
  5. {
  6. public:
  7. CTest(): mValue(100)
  8. {
  9. printf("constructor\n");
  10. }
  11. ~CTest()
  12. {
  13. printf("destructor\n");
  14. }
  15. int getValue()
  16. {
  17. return mValue;
  18. }
  19. private:
  20. int mValue;
  21. };
  22. int main()
  23. {
  24. std::weak_ptr<CTest> weakPtr;
  25. std::weak_ptr<CTest> weakPtr2(weakPtr);
  26. std::shared_ptr<CTest> ptr = std::make_shared<CTest>();
  27. std::weak_ptr<CTest> weakPtr3(ptr);
  28. int value = ptr->getValue();
  29. printf("value = %d, use_count = %d\n", value, ptr.use_count());
  30. value = (weakPtr3.lock())->getValue();
  31. printf("value = %d\n", value);
  32. ptr.reset();
  33. auto ptr2 = weakPtr3.lock();
  34. if(ptr2 == nullptr)
  35. {
  36. printf("weakPtr3.lock() = nullptr\n");
  37. return 0;
  38. }
  39. value = ptr2->getValue();
  40. return 0;
  41. }

二,expired() 成员函数

bool expired() const noexcept; 函数返回 weak_ptr 对象是否是空的,或是它所属的所有者组中不再有shared_ptr。此函数与 use_count() == 0 意义相同。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory>
  4. class CTest
  5. {
  6. public:
  7. CTest(): mValue(100)
  8. {
  9. printf("constructor\n");
  10. }
  11. ~CTest()
  12. {
  13. printf("destructor\n");
  14. }
  15. int getValue()
  16. {
  17. return mValue;
  18. }
  19. private:
  20. int mValue;
  21. };
  22. int main()
  23. {
  24. std::weak_ptr<CTest> weakPtr;
  25. std::weak_ptr<CTest> weakPtr2(weakPtr);
  26. std::shared_ptr<CTest> ptr = std::make_shared<CTest>();
  27. std::weak_ptr<CTest> weakPtr3(ptr);
  28. if(weakPtr.expired())
  29. {
  30. printf("weakPtr is empty!\n");
  31. }
  32. if(weakPtr2.expired())
  33. {
  34. printf("weakPtr2 is empty!\n");
  35. }
  36. if(weakPtr3.expired())
  37. {
  38. printf("weakPtr3 is empty!\n");
  39. }
  40. return 0;
  41. }

我们可以看到源码是这样的:

三,lock() 成员函数

shared_ptr<element_type> lock() const noexcept; 函数返回一个shared_ptr,其中包含weak_ptr对象在未过期时保留的信息。如果 weak_ptr 对象已过期(包括它是否为空),该函数将返回一个空的shared_ptr(就像默认构造的一样)。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <memory>
  4. class CTest
  5. {
  6. public:
  7. CTest(): mValue(100)
  8. {
  9. printf("constructor\n");
  10. }
  11. ~CTest()
  12. {
  13. printf("destructor\n");
  14. }
  15. int getValue()
  16. {
  17. return mValue;
  18. }
  19. private:
  20. int mValue;
  21. };
  22. int main()
  23. {
  24. std::weak_ptr<CTest> weakPtr;
  25. std::weak_ptr<CTest> weakPtr2(weakPtr);
  26. std::shared_ptr<CTest> ptr = std::make_shared<CTest>();
  27. std::weak_ptr<CTest> weakPtr3(ptr);
  28. std::shared_ptr<CTest> lck;
  29. lck = weakPtr.lock();
  30. if(lck == nullptr)
  31. {
  32. printf("weakPtr is empty!\n");
  33. }
  34. if(!weakPtr2.lock())
  35. {
  36. printf("weakPtr2 is empty!\n");
  37. }
  38. std::shared_ptr<CTest> test;
  39. if((test = weakPtr3.lock()) != nullptr)
  40. {
  41. printf("weakPtr3 is not empty! value = %d\n", test->getValue());
  42. }
  43. return 0;
  44. }

在使用 lock() 函数时,可以判断其是否为nullptr。当用 gdb 查看时可以看到:lck=weakPtr.lock()后,lck 就是 0。 

我们可以看源码 lock() 函数是怎样实现的:

可以看到当对象过期时,构造了一个空的 shared_ptr<>对象进行返回,而这个空对象它的初始化值是这样的:

_M_ptr 是模板参数类型的指针,它指向的就是要管理的对象。而 _M_refcount  是管理引用计数的。所以一个空的 shared_ptr<> 并不管理任何对象,就不能当作对象指针来用了。但 use_count() 还是可以用的,用 lck.use_count() == 0 进行判断:

 

这里可能会有人疑问:lck 都是nullptr 了,怎么还能调用 use_count() 呢?这样调用不会崩溃吗?这个就要理解类与对象的关系了,可以参考 null 类对象。可以看源码:

四,use_count() 成员函数

weak_ptr 里有两个计数,一个是 _M_use_count 管理对象的引用计数,一个是 _M_weak_count 是不是用于它本身的析构用的,还没研究。weak_ptr 的基类:

  1. _Tp* _M_ptr; // Contained pointer.
  2. __weak_count<_Lp> _M_refcount; // Reference counter.
  1. template<_Lock_policy _Lp>
  2. class __weak_count
  3. {
  4. public:
  5. constexpr __weak_count() noexcept : _M_pi(0)
  6. { }
  7. __weak_count(const __shared_count<_Lp>& __r) noexcept
  8. : _M_pi(__r._M_pi)
  9. {
  10. if (_M_pi != 0)
  11. _M_pi->_M_weak_add_ref();
  12. }

 __weak_count<_Lp> 模板类有一个成员 _M_pi, 其类型为 _Sp_counted_base<_Lp>*  _M_pi;

 _Sp_counted_base<_Lp> 就包含上述的两个计数。use_count() 函数调用的是_M_refcount._M_get_use_count(); 

五,为什么要用 weak_ptr

1,解决shared_ptr 循环引用的问题。这个网上也有很多例子

2,在不延长shared_ptr 管理对象生命周期的情况下,探知这个对象是否已经无效。可以参考 muduo 的例子​​​​​​​

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

闽ICP备14008679号