智能指针 梦里梦外; 2022-07-17 03:43 320阅读 0赞 **RAII(Resource Acquisition Is Initialization):** 资源分配即初始化,定义封装一个类,用来实现调用构造函数时就可完成资源的分配和初始化,在调用析构函数就可完成资源的清理,以实现对资源的初始化和清理。 **智能指针:** 用自动化或者说智能的指针来实现对动态内存的释放。 它是一个类,有类似指针的功能。 常见的智能指针有:auto\_ptr/scoped\_ptr/scoped\_array/shared\_ptr/shared\_array **一、AutoPtr** 首先,先介绍AutoPtr,为防止一块空间释放两次浅拷贝导致的崩溃情况,我们的思想是权限转移,就是说你拷贝时要将你的两个指针指向同一块空间,可是这样会程序崩溃。解决如下: **1)老版AutoPtr** 主要变量是\_ptr,\_owner,用bool型的\_owner来控制权限转移,当它为false值时释放空间,保证释放一次。 **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. 4. **template**<**class** T> 5. **class** AutoPtr 6. \{ 7. **public**: 8. AutoPtr(T\* ptr = NULL) 9. :\_ptr(ptr) 10. , \_owner(**true**) 11. \{\} 12. 13. AutoPtr(**const** AutoPtr<T>& ap) 14. :\_ptr(ap.\_ptr) 15. \{ 16. ap.\_owner = **false**; 17. \_owner = **true**; 18. \} 19. 20. AutoPtr<T>& operator=(**const** AutoPtr<T>& ap) 21. \{ 22. **if** (&s != **this**) 23. \{ 24. **delete** \_ptr; 25. \_ptr = ap.\_ptr; 26. ap.\_owner = **false**; 27. \_owner = **true**; 28. \} 29. **return** \***this**; 30. \} 31. 32. ~AutoPtr() 33. \{ 34. **if** (\_ptr) 35. \{ 36. **delete** \_ptr; 37. \_ptr = NULL; 38. \_owner = **false**; 39. \} 40. \} 41. 42. T\* operator->() 43. \{ 44. **return** \_ptr; 45. \} 46. 47. T& operator\*() 48. \{ 49. **return** \*\_ptr; 50. \} 51. **private**: 52. T\* \_ptr; 53. **bool** \_owner; 54. \}; 55. 56. **void** Test() 57. \{ 58. AutoPtr<**int**> ap1(**new** **int**(1)); 59. AutoPtr<**int**> ap2(ap1); 60. AutoPtr<**int**> ap3 = ap1; 61. \} 62. 63. **int** main() 64. \{ 65. Test(); 66. system("pause"); 67. **return** 0; 68. \} 缺陷: **\[cpp\]** [view plain][] [copy][view plain] 1. **if**(……) 2. \{ 3. AutoPtr<**int**> ap2(ap1); 4. …… 5. \} 出了作用域后ap2会释放空间还给系统,而ap2仍指向这块空间,会出现野指针。 ![wKioL1b3owbibxRCAAATFI5Rwkc178.png][] **2)新版AutoPtr** 我们及时将之前的指针置成空,将这块空间的所有权交给现在的指针。 -------------------- **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. 4. **template**<**class** T> 5. **class** AutoPtr 6. \{ 7. **public**: 8. AutoPtr(T\* ptr) 9. :\_ptr(ptr) 10. \{\} 11. 12. AutoPtr() 13. :\_ptr(NULL) 14. \{\} 15. 16. AutoPtr<T>(AutoPtr<T>& ap) //权限转移 17. : \_ptr(ap.\_ptr) 18. \{ 19. ap.\_ptr = NULL; 20. \} 21. 22. AutoPtr<T>& operator=(AutoPtr<T>& ap) 23. \{ 24. **if** (&ap != **this**) 25. \{ 26. **delete** \_ptr; 27. \_ptr = ap.\_ptr; 28. ap.\_ptr = NULL; //权限转移 29. \} 30. **return** \***this**; 31. \} 32. 33. ~AutoPtr() 34. \{ 35. **if** (\_ptr) 36. \{ 37. **delete** \_ptr; 38. \_ptr = NULL; 39. \} 40. \} 41. 42. T& operator\*() 43. \{ 44. **return** \*\_ptr; 45. \} 46. 47. **private**: 48. T\* \_ptr; 49. \}; 50. 51. **void** Test() 52. \{ 53. AutoPtr<**int**> ap1(**new** **int**(2)); 54. AutoPtr<**int**> ap2 = ap1; 55. AutoPtr<**int**> ap3(**new** **int**(3)); 56. ap3 = ap1; 57. \} 58. 59. **int** main() 60. \{ 61. Test(); 62. system("pause"); 63. **return** 0; 64. \} **二、ScopedPtr** 这是最实用的智能指针。 顾名思义,守卫的指针,思想就是防拷贝,在大多时候用不到拷贝构造和赋值运算符重载,那么我们做的就是写出构造函数和析构函数,拷贝构造和赋值运算符重载只声明不定义。这里有几点要说明: **(1)**鉴于上面,我们写智能指针时,将拷贝构造和赋值运算符重载设置成保护或者私有的,这样就可以保证其他人在不知情的情况下(以为是我们忘记写定义了)无法写拷贝构造和赋值运算符重载的定义。 **(2)**既然不要定义,那为什么要声明呢,是不是可以不要,或许你们会这样想。不可以!原因是你不写,编译器会自动调用系统自身的拷贝构造和赋值运算符重载,这样就没办法做到防拷贝了。 下面,我们用ScopedPtr来实现简易版本的智能指针。 -------------------- **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. 4. **template**<**class** T> 5. **class** ScopedPtr 6. \{ 7. **public**: 8. ScopedPtr(T\* ptr) 9. :\_ptr(ptr) 10. \{\} 11. 12. Scoped() 13. :\_ptr(NULL) 14. \{\} 15. 16. ~ScopedPtr() 17. \{ 18. **if** (\_ptr) 19. \{ 20. **delete** \_ptr; 21. \_ptr = NULL; 22. \} 23. \} 24. 25. T& operator\*() 26. \{ 27. **return** \*\_ptr; 28. \} 29. 30. T\* GetPtr() 31. \{ 32. **return** \_ptr; 33. \} 34. 35. **protected**: 36. ScopedPtr<T>(**const** ScopedPtr<T>& sp); 37. ScopedPtr<T>& operator = (**const** ScopedPtr<T>& sp); 38. 39. **private**: 40. T\* \_ptr; 41. \}; 42. 43. **void** Test() 44. \{ 45. ScopedPtr<**int**> sp1(**new** **int**(2)); 46. ScopedPtr<**int**> sp2 = sp1; 47. ScopedPtr<**int**> sp3(**new** **int**(3)); 48. sp3 = sp1; 49. \} 50. 51. **int** main() 52. \{ 53. Test(); 54. system("pause"); 55. **return** 0; 56. \} **三、SharedPtr** 共享指针,即思想就是引用计数,引入变量指针变量pCount,指向一块空间,对其计数,当只有一个指针指向空间时再释放资源,实现对其管理。初衷也是解决多个指针指向同一块空间释放多次会崩溃。这里不用static的整型的pCount在于,若有多个指针指向第一块空间,多个指针指向第二块空间,……,当改变一块空间的指向,该块空间的引用计数发生变化了,static的pCount会导致其他空间的引用计数也发生变化。 **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. 4. **template**<**class** T> 5. **class** SharedPtr 6. \{ 7. **public**: 8. SharedPtr(T\* ptr) 9. :\_ptr(ptr) 10. , \_pCount(**new** **long**(1)) 11. \{\} 12. 13. SharedPtr() 14. :\_ptr(NULL) 15. , \_pCount(**new** **long**(1)) 16. \{\} 17. 18. SharedPtr<T>(**const** SharedPtr<T>& sp) 19. : \_ptr(sp.\_ptr) 20. , \_pCount(sp.\_pCount) 21. \{ 22. ++(\*\_pCount); 23. \} 24. 25. SharedPtr<T>& operator=(**const** SharedPtr<T>& sp) 26. \{ 27. **if** (&sp != **this**) 28. \{ 29. **if** (--(\*\_pCount) == 0) 30. \{ 31. **delete** \_ptr; 32. **delete** \_pCount; 33. \} 34. \_ptr = sp.\_ptr; 35. \_pCount = sp.\_pCount; 36. ++(\*\_pCount); 37. \} 38. **return** \***this**; 39. \} 40. 41. ~SharedPtr() 42. \{ 43. **if** (\_ptr) 44. \{ 45. **if** (--(\*\_pCount) == 0) 46. \{ 47. **delete** \_ptr; 48. **delete** \_pCount; 49. \} 50. \} 51. \} 52. 53. T& operator\*() 54. \{ 55. **return** \*\_ptr; 56. \} 57. 58. **long** GetCount() 59. \{ 60. **return** \*(\_pCount); 61. \} 62. 63. T\* GetPtr() 64. \{ 65. **return** \_ptr; 66. \} 67. 68. **private**: 69. T\* \_ptr; 70. **long**\* \_pCount; 71. \}; 72. 73. 74. **void** Test() 75. \{ 76. SharedPtr<**int**> sp1 = **new** **int**(1); 77. SharedPtr<**int**> sp2 = sp1; 78. SharedPtr<**int**> sp3 = **new** **int**(2); 79. sp3 = sp1; 80. \} 81. 82. 83. **int** main() 84. \{ 85. Test(); 86. system("pause"); 87. **return** 0; 88. \} **四、ScopedArray** ScopedArray与ScopedPtr区别在于: ScopedArray管理数组,不可实现访问单个元素,而ScopedArray数组,可实现对数组元素的操控。 **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. \#include<assert.h> 4. 5. 6. **template**<**class** T> 7. **class** ScopedArray 8. \{ 9. **public**: 10. ScopedArray(T\* ptr = NULL) 11. :\_ptr(ptr) 12. \{\} 13. 14. ~ScopedArray() 15. \{ 16. **if** (\_ptr) 17. \{ 18. **delete** \[\] \_ptr; 19. \_ptr = NULL; 20. \} 21. \} 22. 23. T& operator\[\](**size\_t** index) 24. \{ 25. assert(index > 0); 26. **return** \_ptr\[index\]; 27. \} 28. 29. **protected**: 30. ScopedArray<T>(**const** ScopedArray<T>& sp); 31. ScopedArray<T>& operator=(**const** ScopedArray<T>& sp); 32. 33. **private**: 34. T\* \_ptr; 35. \}; 36. 37. **void** Test() 38. \{ 39. ScopedArray<**int**> sp1(**new** **int**\[10\]); 40. \} 41. 42. **int** main() 43. \{ 44. Test(); 45. \} **五、SharedPtr** **同四。** **\[cpp\]** [view plain][] [copy][view plain] 1. \#include<iostream> 2. **using** **namespace** std; 3. \#include<assert.h> 4. 5. **template**<**class** T> 6. **class** SharedArray 7. \{ 8. **public**: 9. SharedArray(T\* ptr = NULL) 10. :\_ptr(ptr) 11. , \_pCount(**new** **long**(1)) 12. \{\} 13. 14. SharedArray<T>(**const** SharedArray<T>& sp) 15. : \_ptr(sp.\_ptr) 16. \{ 17. (\*\_pCount)++; 18. \} 19. 20. SharedArray<T> operator=(**const** SharedArray<T>& sp) 21. \{ 22. **if** (&s != **this**) 23. \{ 24. **if** (--(\*pCount) == 0) 25. \{ 26. **delete** \_ptr; 27. \_ptr = sp.\_ptr; 28. (\*pCount)++; 29. \} 30. \} 31. **return** \***this**; 32. \} 33. 34. ~SharedArray() 35. \{ 36. **if** (\_ptr) 37. \{ 38. **if** (--(\*\_pCount) == 0) 39. \{ 40. **delete** \_ptr; 41. **delete** \_pCount; 42. \_ptr = NULL; 43. \_pCount = NULL; 44. \} 45. \} 46. \} 47. 48. T\* operator\[\](**size\_t** index) 49. \{ 50. assert(index); 51. **return** \_ptr\[index\]; 52. \} 53. **private**: 54. T\* \_ptr; 55. **long** \*\_pCount; 56. \}; 57. 58. 59. **void** Test() 60. \{ 61. SharedArray<**int**> sp1(**new** **int**\[10\]); 62. SharedArray<**int**> sp2(sp1); 63. SharedArray<**int**> sp3 = sp1; 64. \} 65. 66. **int** main() 67. \{ 68. Test(); 69. system("pause"); 70. **return** 0; 71. \} 72. [view plain]: http://blog.csdn.net/hanjing_1995/article/details/51539574# [wKioL1b3owbibxRCAAATFI5Rwkc178.png]: /images/20220717/bc605c5e5d8b4c628ae3335e4dbf5815.png
相关 智能指针 C++里面的四个智能指针分别是:auto\_ptr,shared\_ptr,weak\_ptr,unique\_ptr,其中后三个是C++11支持的,第一个auto\_ptr已 客官°小女子只卖身不卖艺/ 2023年10月09日 12:14/ 0 赞/ 158 阅读
相关 智能指针 智能指针 1.引入使用计数 定义智能指针的通用技术是采用一个使用计数。智能指针将一个计数器与类指向的对象相关联。使用计数跟踪该类有多少个对象共享同一指针。使用计数为0时 Bertha 。/ 2023年06月23日 15:29/ 0 赞/ 110 阅读
相关 智能指针 智能指针 智能指针的智能,体现在智能指针能够在每次完成工作之后自动释放占用的空间。 我们通常使用的裸指针,使用完成后需要通过delete或者free来进行释放,那么如 向右看齐/ 2023年06月21日 03:46/ 0 赞/ 43 阅读
相关 智能指针 有三个智能指针,auto\_ptr(弃用)、unique\_ptr、shared\_ptr. 智能指针可以自动跟踪动态内存,在其过期时自动释放。 include< ゝ一纸荒年。/ 2023年02月21日 14:05/ 0 赞/ 143 阅读
相关 智能指针 class MyClass { public: MyClass(int a){}; ~MyClass() 逃离我推掉我的手/ 2023年01月03日 12:54/ 0 赞/ 282 阅读
相关 c++ 智能指针 前言 C++里面的四个智能指针: auto\_ptr, unique\_ptr,shared\_ptr, weak\_ptr 其中后三个是C++11支持,并且第一个已经被 左手的ㄟ右手/ 2022年09月07日 12:15/ 0 赞/ 373 阅读
相关 智能指针 scoped\_ptr解析 《超越C++标准库-Boost库导论》 头文件: "boost/scoped\_ptr.hpp" boost::scoped\_ptr 用于确 超、凢脫俗/ 2022年08月09日 16:37/ 0 赞/ 350 阅读
相关 智能指针 RAII(Resource Acquisition Is Initialization): 资源分配即初始化,定义封装一个类,用来实现调用构造函数时就可完成资源的分 梦里梦外;/ 2022年07月17日 03:43/ 0 赞/ 321 阅读
相关 智能指针 在C++中,如果指针使用不当,比如没有及时释放指针所指向的内存,或者野指针等,会造成系统发生不可预估的错误,为了防止这一情况的发生,C++ STL提供了一系列智能指针类型 智 偏执的太偏执、/ 2022年05月17日 07:29/ 0 赞/ 360 阅读
相关 智能指针 智能指针 在java中如果在堆上开辟内存是不需要手动释放的,我们叫做智能指针;但是在C++中如果用new在堆上开辟了空间,我们需要用delete进行手动释放,否则造 悠悠/ 2022年03月18日 11:54/ 0 赞/ 384 阅读
还没有评论,来说两句吧...