C++——智能指针 weak_ptr
weak_ptr这个指针天生一副小弟的模样也是在C11的时候引入的标准库它的出现完全是为了弥补它老大shared_ptr天生有缺陷的问题。只能配合shared_ptr一起使用。shared_ptr循环引用造成的后果存在资源泄露一、shared_ptr 的循环引用什么是循环引用的问题呢在shared_ptr的使用过程中当强引用计数为0时就会释放所指向的堆内存。那么问题来了如果和死锁一样当两个shared_ptr互相引用那么它们就永远无法被释放了。循环引用指的是两个或者多个对象互相持有对方的’std::shared_ptr‘使得引用计数永远不会将为0从而导致资源无法释放struct ListNode { int _data; shared_ptrListNode _prev; shared_ptrListNode _next; ~ListNode() { cout ~ListNode() endl; } }; int main() { shared_ptrListNode node1(new ListNode); shared_ptrListNode node2(new ListNode); node1-_next node2; node2-_prev node1; return 0; }以上代码运行检测到如下内存泄露分析定义出来的sp1和sp2都有如下的结构 首先sp1是一个智能指针shared_ptr所以它有它的_ptr和_pCount字段其次ListNode结构的结点内部有三个成员变量分别为data next prev而且这个next和prev它俩也是俩个shared_ptr智能指针对象也有其自己的_ptr和_pCount于是定义出来的sp1对象就有如下的结构。sp2结构也和此图一致。经过如下的链接操作后形成如下图的链接结构。node1-_next node2; node2-_prev node1;随后程序执行结束进入到对象的析构环节后创建的元素先析构先进行sp2对象的析构根据shared_ptr计数功能对右边计数器进行--操作发现计数器无法归零所以不能对sp2资源进行释放转而进行sp1对象的析构处理但是对左侧计数器进行--操作后发现仍然不能归零俩个对象中的next和prev分别造成了不同计数器的无法归零就导致内存泄露资源无法回收。二、weak_ptr 解决循环引用标准库提供了weak_ptr唯一作用就是帮助shared_ptr解决循环引用的问题weak_ptr不能管理资源只能配合shared_ptr一起使用。如此修改之后俩个对象正常进行析构并且没有产生资源泄露。三、为什么weak_ptr能解决这个问题weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。可以看到上图的代码运行结果打印出来的就是sp1和sp2俩个对象的引用计数发现在进行next和pre指针的指向链接后并没有对sp1和sp2对象的引用计数更改。weak_ptr的原理weak_ptr是为了配合shared_ptr而引入的一种智能指针它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期也就是将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。不论是否有weak_ptr指向一旦最后一个指向对象的shared_ptr被销毁对象就会被释放。从这个角度看weak_ptr更像是shared_ptr的一个助手而不是智能指针。实际shared_ptr源码中存在俩个变量来进行计数一个是use_count 一个是weak_count 它俩的初始化均为1use也就是我们之前一直打印出来的当前对象有关联的对象计数个数而weak就是这个shared_ptr指针所管理的资源weak_ptr类型的变量个数。下图即为在next和prev连接后的结果图此时use_count均为1weak_ptr均为2