• C++笔记-auto_ptr&unique_ptr&shared_ptr&shared_ptr基本用法


    前一篇博文的笔记是:C++文档阅读笔记-Smart Pointers in C++ and How to Use Them

    这里Geek大体介绍了智能指针的基本,但感觉不是很具体,在此补充下例子,方便以后查阅。

    本次例子主要是使用这4种类型的智能指针

    代码如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. using namespace::std;
    6. class Rectangle{
    7. public:
    8. Rectangle(int l, int b){
    9. length = l;
    10. breadth = b;
    11. }
    12. ~Rectangle(){
    13. qDebug() << "~Rectangle() called";
    14. }
    15. int area(){
    16. return length * breadth;
    17. }
    18. private:
    19. int breadth;
    20. int length;
    21. };
    22. void autoPtr(){
    23. qDebug() << "void autoPtr()";
    24. auto_ptr ptr1(new Rectangle(10, 5));
    25. qDebug() << "ptr1->area() : " << ptr1->area();
    26. auto_ptr ptr2(ptr1);
    27. qDebug() << "ptr2->area() : " << ptr2->area();
    28. }
    29. void uniquePtr(){
    30. qDebug() << "void uniquePtr()";
    31. unique_ptr ptr1(new Rectangle(10, 2));
    32. qDebug() << "ptr1->area() : " << ptr1->area();
    33. unique_ptr ptr2 = move(ptr1);
    34. qDebug() << "ptr2->area() : " << ptr2->area();
    35. }
    36. void sharedPtr(){
    37. qDebug() << "void sharedPtr()";
    38. shared_ptr ptr1(new Rectangle(1, 2));
    39. qDebug() << "ptr1->area() : " << ptr1->area();
    40. qDebug() << "ptr1.use_count() : " << ptr1.use_count();
    41. shared_ptr ptr2(ptr1);
    42. qDebug() << "ptr2->area() : " << ptr2->area();
    43. qDebug() << "ptr2.use_count() : " << ptr2.use_count();
    44. qDebug() << "ptr1.use_count() : " << ptr1.use_count();
    45. }
    46. void weakPtr(){
    47. qDebug() << "void weakPtr()";
    48. shared_ptr ptr1(new Rectangle(100, 1));
    49. qDebug() << "ptr1->area() : " << ptr1->area();
    50. qDebug() << "ptr1.use_count() : " << ptr1.use_count();
    51. weak_ptr ptr2 = ptr1;
    52. qDebug() << "ptr1.use_count() : " << ptr1.use_count();
    53. qDebug() << "ptr2.lock()->area() : " << ptr2.lock()->area();
    54. }
    55. int main(int argc, char *argv[])
    56. {
    57. QCoreApplication a(argc, argv);
    58. autoPtr();
    59. qDebug() << "";
    60. uniquePtr();
    61. qDebug() << "";
    62. sharedPtr();
    63. qDebug() << "";
    64. weakPtr();
    65. return a.exec();
    66. }

    运行截图如下:

    这里就简单来看下auto_ptr,我这里是windows平台:

    1. #if _HAS_AUTO_PTR_ETC
    2. // TEMPLATE CLASS auto_ptr
    3. template<class _Ty>
    4. class auto_ptr;
    5. template<class _Ty>
    6. struct auto_ptr_ref
    7. { // proxy reference for auto_ptr copying
    8. explicit auto_ptr_ref(_Ty *_Right)
    9. : _Ref(_Right)
    10. { // construct from generic pointer to auto_ptr ptr
    11. }
    12. _Ty *_Ref; // generic pointer to auto_ptr ptr
    13. };
    14. template<class _Ty>
    15. class auto_ptr
    16. { // wrap an object pointer to ensure destruction
    17. public:
    18. typedef auto_ptr<_Ty> _Myt;
    19. typedef _Ty element_type;
    20. explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
    21. : _Myptr(_Ptr)
    22. { // construct from object pointer
    23. }
    24. auto_ptr(_Myt& _Right) _THROW0()
    25. : _Myptr(_Right.release())
    26. { // construct by assuming pointer from _Right auto_ptr
    27. }
    28. auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
    29. { // construct by assuming pointer from _Right auto_ptr_ref
    30. _Ty *_Ptr = _Right._Ref;
    31. _Right._Ref = 0; // release old
    32. _Myptr = _Ptr; // reset this
    33. }
    34. template<class _Other>
    35. operator auto_ptr<_Other>() _THROW0()
    36. { // convert to compatible auto_ptr
    37. return (auto_ptr<_Other>(*this));
    38. }
    39. template<class _Other>
    40. operator auto_ptr_ref<_Other>() _THROW0()
    41. { // convert to compatible auto_ptr_ref
    42. _Other *_Cvtptr = _Myptr; // test implicit conversion
    43. auto_ptr_ref<_Other> _Ans(_Cvtptr);
    44. _Myptr = 0; // pass ownership to auto_ptr_ref
    45. return (_Ans);
    46. }
    47. template<class _Other>
    48. _Myt& operator=(auto_ptr<_Other>& _Right) _THROW0()
    49. { // assign compatible _Right (assume pointer)
    50. reset(_Right.release());
    51. return (*this);
    52. }
    53. template<class _Other>
    54. auto_ptr(auto_ptr<_Other>& _Right) _THROW0()
    55. : _Myptr(_Right.release())
    56. { // construct by assuming pointer from _Right
    57. }
    58. _Myt& operator=(_Myt& _Right) _THROW0()
    59. { // assign compatible _Right (assume pointer)
    60. reset(_Right.release());
    61. return (*this);
    62. }
    63. _Myt& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
    64. { // assign compatible _Right._Ref (assume pointer)
    65. _Ty *_Ptr = _Right._Ref;
    66. _Right._Ref = 0; // release old
    67. reset(_Ptr); // set new
    68. return (*this);
    69. }
    70. ~auto_ptr() _NOEXCEPT
    71. { // destroy the object
    72. delete _Myptr;
    73. }
    74. _Ty& operator*() const _THROW0()
    75. { // return designated value
    76. #if _ITERATOR_DEBUG_LEVEL == 2
    77. if (_Myptr == 0)
    78. _DEBUG_ERROR("auto_ptr not dereferencable");
    79. #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
    80. return (*get());
    81. }
    82. _Ty *operator->() const _THROW0()
    83. { // return pointer to class object
    84. #if _ITERATOR_DEBUG_LEVEL == 2
    85. if (_Myptr == 0)
    86. _DEBUG_ERROR("auto_ptr not dereferencable");
    87. #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
    88. return (get());
    89. }
    90. _Ty *get() const _THROW0()
    91. { // return wrapped pointer
    92. return (_Myptr);
    93. }
    94. _Ty *release() _THROW0()
    95. { // return wrapped pointer and give up ownership
    96. _Ty *_Tmp = _Myptr;
    97. _Myptr = 0;
    98. return (_Tmp);
    99. }
    100. void reset(_Ty *_Ptr = 0)
    101. { // destroy designated object and store new pointer
    102. if (_Ptr != _Myptr)
    103. delete _Myptr;
    104. _Myptr = _Ptr;
    105. }
    106. private:
    107. _Ty *_Myptr; // the wrapped object pointer
    108. };
    109. #endif /* _HAS_AUTO_PTR_ETC */
    110. _STD_END

     

    这里以auto_ptr为例,研究2个问题:

    ①auto_ptr是如何调用传给他的原始指针;

    ②auto_ptr是如何实现原始指针的析构。

    从中可以看到:

    其实auto_ptr就是一封装类,他将传入的指针放到了_Ty中,命名为_Myptr。

    构造函数要将需要变智能的指针传进来,给_Myptr赋值。

     这里可以看到,但调用->这个符号后,他先看_Myptr有无值,如果有就调用get()方法。

    如果是要使用*这个负荷:

    就会传*get()过来,这里差不多就可以猜到,这个get()方法,返回的就是_Myptr

    从中可以看到,的确,get方法返回被包裹的指针。第一个问题就研究完了,

    下面来看第二个问题,他是如何实现资源的释放的。

     

    看到这里想必都已经明白了,auto_ptr一般是在栈区进行创建,当栈区生命周期结束后,调用其自己的析构函数,而他自己的析构函数里面对_Myptr进行了delete。

  • 相关阅读:
    LeetCode解法汇总2591. 将钱分给最多的儿童
    深度学习入门之线性代数(PyTorch)
    [C#]使用C#部署yolov8的目标检测tensorrt模型
    进程状态和优先级【Linux】
    广告制作如何高效完成视频视频审片?
    ubuntu 源码编译安装make过程很慢问题解决
    word实用小技巧
    22.2 正则表达式-数据验证、数据变换
    2022 年最新【Java 经典面试 800 题】面试必备,查漏补缺;多线程 +spring+JVM 调优 + 分布式 +redis+ 算法
    二十四节气之处暑
  • 原文地址:https://blog.csdn.net/qq78442761/article/details/126711969