17、什么是智能指针,C++有哪几种智能指针【高频】
智能指针其实不是指针,而是一个(模板)类,用来存储指向某块资源的指针,并自动释放这块资源,从而解决内存泄漏问题。主要有以下四种:
- auto_ptr
它的思想就是当当一个指针对象赋值给另一个指针对象的时候,原来的指针就会指向null。因为这个指针已经指向null,之后就不能发挥作用了。现在C++11新特性已经不使用它了
- unique_ptr
在内部实现里,它的 拷贝构造函数 和 复制重载函数 被禁用了,所以它的指针对象时不能进行拷贝和赋值。也就是说,最多只有一个unique_ptr指针指向一块资源
- shared_ptr
shared_ptr允许多个智能指针可以指向同一块资源,并且可以保证 在销毁时共享资源只被释放一次。(普通指针和 shared_ptr是不能指向同一块资源的)
(不能将指针直接赋值给一个智能指针,一个是类,一个是指针。例如:shared_ptr p4 = new int(1) 的写法是错误的!)
- 它主要是通过 引用计数 来实现的:每当一个指针指针对象被销毁,引用计数就会减1,而指针所指内存(即共享资源)不发生变化。当引用计数的值减为0时,它才会释放共享资源。所以引用计数反映的是 这块资源上被多少个指针指向了。

- 销毁过程:
- 当ptr1和ptr2指向的资源不同时,如果令ptr2=ptr1(把ptr1的资源赋值给ptr2,即ptr2指向ptr1的资源):
- 普通指针和 shared_ptr是不能指向同一块资源的:
-
循环引用问题:
- 当创建出node1和node2智能指针对象时,引用计数都是1.
- 当node1的next指向node2所指向的资源时,node2的引用计数就+1,变成2,node2的pre指向noede1所指向的资源时,node1的引用计数+1,变成2.
- 当这两个智能指针使用完后,调用析构函数,引用计数都-1,都变成1,由于引用计数不为0,所以node1和node2所指向的对象不会被释放。
- 当node1所指向的资源释放需要当node2中的_prev被销毁,就需要node2资源的释放,node2所指向的资源释放就需要当node1中的_next被销毁,就需要node1资源的释放。因此node1和node2都有对方的“把柄”,这两个就造成循环引用现象,最终这node1和node2资源就不会进行释放。
-
循环引用问题的解决方法:
使用weak_ptr指针。 weak_ptr指针可以指向智能指针所指的内存,而且不增加智能指针的引用计数。所以我们需要在可能引起 循环引用 的地方,把其他的shared_ptr改成weak_ptr指针
-
weak_ptr对象指向shared_ptr对象时,不会增加shared_ptr中的引用计数,因此当node1销毁掉时,则node1指向的空间就会被销毁掉,node2类似,所以weak_ptr指针可以很好解决循环引用的问题。
-
所以在定义双向链表或者在二叉树等有多个指针的时候,如果想要将该类型定义成智能指针,那么结构体内的指针需要定义成weak_ptr类型的指针,防止循环引用的出现。
-
-
weak_ptr
也就是刚刚所提到的用于解决循环引用的指针。它不能单独使用,必须配合shared_ptr来使用,专门用于解决循环引用问题