智能指针和循环引用

智能指针(四个)

智能指针:实际上是一个栈上的对象,并不是一个指针类型。所有的智能指针都重载了operator ->来访问对象的引用,所以weak_ptr不能算智能指针 因为它没有重载->和*。

RALL机制:通过利用对象的自动销毁,让资源具有了生命周期,有了自动回收的功能。

智能指针由三大版本
1. 管理权转移(std::Autoptr)
2. 简单粗暴的防拷贝(boost::scoped_ptr)
3. 引用计数(boost::shared_ptr)

std::Autoptr
方便管理单个堆内存对象
这里写图片描述
一般不推荐使用std::Autoptr,使用了绝对不能使用=和拷贝构造。

boost::scoped_ptr
scoped_ptr属于boost库,包含头文件 boost/smart_ptr.hpp
它和Autoptr一样方便管理单个堆内存对象
但是scoped_ptr是独享管理权的,它直接告诉用户它不提供=和拷贝构造。

boost::shared_ptr
使用引用计数的方法,当指向该片资源的引用计数变成0时,就释放资源
但是,shared_ptr有一个缺陷就是循环引用。
何为循环引用?
通俗的讲就是 你中有我,我中有你。
举个例子来说:
用shared_ptr构造两个双向链表中的节点(cur和next)
每个节点中也有两个shared_ptr(_next和_prev)
这里写图片描述
运行 cur->_next = next; next->_prev = cur; 后
每个结点都有两个智能指针来管理着(黑色箭头和红色箭头)
这个时候函数运行完毕,cur和next智能指针调用自己的析构函数,每个节点的引用计数减1,然后现在只有一个智能指针管理着节点了(红色),这时_next和_prev也要调用自己的析构函数。
这时问题来了:
_next看来他所指向的节点所有成员都是他的作用域,他要把这整个指向的节点析构,同理_prev也是这样看来。
就这样_next等_prev处理完自己的事,析构_prev
_prev等_next处理完自己的事,析构_next
这样相互等着,谁也不去析构所指向的节点。
这就是循环引用,循环引用会导致内存泄漏!!!

那么如何解决循环引用呢?——weak_ptr

前面说了weak_ptr不能算智能指针 因为它没有重载->和*。
那它是什么呢?可以这样理解,它是shared_ptr的一个帮手!!

weak_ptr是shared_ptr的一个观察者!它只对shared_ptr进行了引用,而没有改变shared_ptr的引用计数!

当weak_ptr看到shared_ptr失效后,weak_ptr也会相应的失效

这里我们回到刚才链表的那个例子。将cur和next定义成weak_ptr,当cur和next析构时,不用引用计数减1,直接删除节点!这就是weak_ptr,不管什么,就是个删!!!

四种智能指针应用!!很重要!!面试经常被问到
1. 在可以使用boost库的场景下,拒绝使用std::Autoptr(管理单个堆对象)
2. 在确定无需对象共享的情况下,使用boost::scoped_ptr(管理单个堆对象)
3. 在对象被共享时,使用boost::shared_ptr
4. 在需要访问boost::shared_ptr对象,又不想改变其引用计数时(循环引用),使用boost::weak_ptr。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值