C++::智能指针

柔情只为你懂 2022-07-18 01:18 437阅读 0赞

1.智能指针的引入场景

先来看看以下这种场景

  1. void fun()
  2. {
  3. int *Pa = new int(10);
  4. //
  5. //
  6. if (1)
  7. throw 1;
  8. //
  9. delete Pa;
  10. }
  11. void test1()
  12. {
  13. try
  14. {
  15. fun();
  16. }
  17. catch (...)
  18. {
  19. cout << "未知异常" << endl;
  20. }
  21. }

我们在fun()里通过动态内存开辟了空间,而当我们在delete 前面由于一些必要的原因必须要抛出一个异常时,delete会由于抛出异常后函数提前终止而没有被执行,从而导致内存泄漏。在这种情况下,我们需要一种能够在出作用域时自动释放内存空间的指针,从而使我们能够避免出现内存泄漏的情况,为此我们引入了智能指针。然而智能指针不是指针,它是一个类,但它能够做指针能做的事情,并且能够通过对象生命周期结束时能够自动调用类的析构函数而达到自动释放内存空间的效果。

2.智能指针的实现

我们主要介绍三种智能指针:

auto_ptr

  1. auto_ptr通过“权限转移"使得不同指针指向的同一块空间不会被析构两次,所谓的“权限转移发生在拷贝构造函数和赋值运算符重载函数当中。
  2. template<class T>
  3. class Auto_ptr //权限转换
  4. {
  5. public:
  6. Auto_ptr(T* _ptr=nullptr)
  7. :m_ptr(_ptr)
  8. {
  9. cout << "Use auto_ptr" << endl;
  10. }
  11. Auto_ptr(Auto_ptr<T>& _ap) //拷贝构造函数
  12. {
  13. if (_ap.m_ptr != NULL)
  14. {
  15. m_ptr = _ap.m_ptr;
  16. }
  17. _ap.m_ptr = NULL;
  18. }
  19. Auto_ptr<T>& operator=(Auto_ptr<T>& _ap)
  20. {
  21. if (m_ptr != NULL)
  22. {
  23. delete m_ptr;
  24. m_ptr = NULL;
  25. }
  26. m_ptr = _ap.m_ptr;
  27. _ap.m_ptr = NULL;
  28. return *this;
  29. }
  30. void Show()
  31. {
  32. cout <<"Show()"<< end;
  33. }
  34. ~Auto_ptr()
  35. {
  36. cout << "~Auto_ptr()" << endl;
  37. if (m_ptr != NULL)
  38. {
  39. delete m_ptr;
  40. m_ptr = NULL;
  41. }
  42. }
  43. T* operator->() const
  44. {
  45. return this->m_ptr;
  46. }
  47. public:
  48. T *m_ptr;
  49. };
  50. template<class T>
  51. class Scope_ptr //不允许赋值
  52. {
  53. public:
  54. Scope_ptr(T* _ptr=nullptr)
  55. :m_ptr(_ptr)
  56. {
  57. cout << "Scope_Ptr()" << endl;
  58. }
  59. ~Scope_ptr()
  60. {
  61. cout << "~Scope_ptr()" << endl;
  62. if (m_ptr != NULL)
  63. {
  64. delete m_ptr;
  65. m_ptr = nullptr;
  66. }
  67. }
  68. T* operator->()
  69. {
  70. return this->m_ptr;
  71. }
  72. private:
  73. Scope_ptr(const Scope_ptr<T>& _ptr);
  74. Scope_ptr<T>& operator=(const Scope_ptr<T>& _ptr);
  75. private:
  76. T* m_ptr;
  77. };

scoped_ptr

  1. scoped_ptrauto_ptr很相似,都是不允许同一个地址空间被两个或多个不同的指针所指向,但是scoped_ptr将这个工作做得更加彻底,他是不允许拷贝构造函数和赋值运算符重载函数发生调用。
  2. template<class T>
  3. class Scope_ptr //不允许赋值
  4. {
  5. public:
  6. Scope_ptr(T* _ptr=nullptr)
  7. :m_ptr(_ptr)
  8. {
  9. cout << "Scope_Ptr()" << endl;
  10. }
  11. ~Scope_ptr()
  12. {
  13. cout << "~Scope_ptr()" << endl;
  14. if (m_ptr != NULL)
  15. {
  16. delete m_ptr;
  17. m_ptr = nullptr;
  18. }
  19. }
  20. T* operator->()
  21. {
  22. return this->m_ptr;
  23. }
  24. private:
  25. Scope_ptr(const Scope_ptr<T>& _ptr);
  26. Scope_ptr<T>& operator=(const Scope_ptr<T>& _ptr);
  27. private:
  28. T* m_ptr;
  29. };

shared_ptr

  1. shared_ptr则显得稍微高端一点,它允许两个指针指向同一块内存地址空间,但是shared_ptr这个类采用了引用计数的方式来维护多个指针指向同一块内存地址空间的问题,它在类中定义了一个指向计数器pCount的指针,当用一个对象创建另一个对象时pCount所指向的计数器值会加1,而在析构函数里,每进来一次析构函数pCount指针所指向的计数器会减1,只有当计数器中的值为0才会释放内存空间。
  2. template<class T>
  3. class Shared_ptr //写时拷贝技术
  4. {
  5. public:
  6. Shared_ptr(T* _ptr=NULL)
  7. :m_ptr(_ptr)
  8. , m_pCount(new int(1))
  9. {
  10. cout << "Shared_ptr()" << endl;
  11. }
  12. Shared_ptr(const Shared_ptr<T>& _sp)
  13. :m_ptr(_sp.m_ptr)
  14. {
  15. cout << "shared_ptr<T>(shared_ptr<T>& _sp)" << endl;
  16. m_pCount = _sp.m_pCount;
  17. ++(*m_pCount);
  18. }
  19. Shared_ptr<T>& operator=(Shared_ptr<T>& _sp)
  20. {
  21. if (this->m_ptr != _sp.m_ptr)
  22. {
  23. if (--(*m_pCount) == 0)
  24. {
  25. delete m_ptr;
  26. delete m_pCount;
  27. m_ptr = NULL;
  28. m_pCount = NULL;
  29. }
  30. m_ptr = _sp.m_ptr;
  31. m_pCount = _sp.m_pCount;
  32. ++(*m_pCount);
  33. }
  34. return *this;
  35. }
  36. T* operator->()
  37. {
  38. return this->m_ptr;
  39. }
  40. Shared_ptr& operator*()
  41. {
  42. return *this;
  43. }
  44. int Get_Count()
  45. {
  46. cout << "Shared_ptr::Count->";
  47. return *m_pCount;
  48. }
  49. T* Get()
  50. {
  51. return this->m_ptr;
  52. }
  53. ~Shared_ptr()
  54. {
  55. if (--(*m_pCount) == 0)
  56. {
  57. cout << "Realse buffer" << endl;
  58. delete m_ptr;
  59. delete m_pCount;
  60. m_ptr = NULL;
  61. m_pCount = NULL;
  62. }
  63. }
  64. private:
  65. T* m_ptr;
  66. int* m_pCount;
  67. };

发表评论

表情:
评论列表 (有 0 条评论,437人围观)

还没有评论,来说两句吧...

相关阅读

    相关 C++ 智能指针

    C++ 智能指针 为了更安全地使用动态对象,标准库定义了两个只能指针类型来管理动态分配的对象当一个对象应该被释放时,指向它的智能指针可以确保自动地把它释放。 理论上来

    相关 C++】智能指针

    在C++中,我们经常会用到动态开辟内存,需要我们自己维护,在出函数作用域之前,必须将管理的内存释放掉,否则就会造成内存泄漏,即使我们十分小心,但总有可能出错,因此便有了智能指针

    相关 C++智能指针

    1.智能指针的作用        C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。程序员自己管理堆内存可以提高了程序的效率,但是整体来说