【C++】智能指针简述(五):解决循环引用的weak_ptr
总结一下前文内容:
1.智能指针通过RAII方法来管理指针:构造对象时,完成资源初始化;析构对象时,对资源进行清理及汕尾.
2.auto_ptr,通过“转移所有权”来防止析构一块内存多次.(如何转移?详情看第二篇文章)
3.scoped_ptr,不“转移所有权”而是禁止拷贝/赋值对象.(C++如何禁止拷贝对象?详情看第三篇文章)
4.shared_ptr,通过"引用计数"的方法,来完成对象的拷贝/赋值.(引用计数怎么实现?详情看上篇文章)
大致总结了一下前文后,我们开始讨论今天的内容:解决智能指针的循环引用问题!
我们先来看一下这样的场景:
template<typename T>
struct ListNode{
T _value;
std::shared_ptr<ListNode> _prev;
std::shared_ptr<ListNode> _next; ListNode(const T & value)
:_value(value)
,_prev(NULL)
,_next(NULL){} ~ListNode(){
std::cout<<"~ListNode()"<<std::endl;
}
}; void TestWeekPtr(){
std::shared_ptr<ListNode<int>> sp1(new ListNode<int>(10));
std::shared_ptr<ListNode<int>> sp2(new ListNode<int>(20));
sp1->_next = sp2;
sp2->_prev = sp1;
//构成死锁,出了函数作用域,也没有调用析构函数
std::cout<<sp1.use_count()<<std::endl; //sp1的引用计数
std::cout<<sp2.use_count()<<std::endl; //sp2的引用计数
}
sp1指向sp2、sp2又指向sp1,这种情况,就好像两个人打架:互相抓住对方耳朵,A说你先松手,你不松我就不松;B说你先松,你不松我也不松.就这样一直僵持着.....
那么,我们如何解决这样的问题呢?
用weak_ptr!!!
template<typename T>
struct ListNode{
T _value;
weak_ptr<ListNode> _prev;
weak_ptr<ListNode> _next; ListNode(const T & value)
:_value(value)
,_prev(NULL)
,_next(NULL){} ~ListNode(){
std::cout<<"~ListNode()"<<std::endl;
}
};
void TestWeekPtr(){
std::shared_ptr<ListNode<int>> sp1(new ListNode<int>(10));
std::shared_ptr<ListNode<int>> sp2(new ListNode<int>(20));
sp1->_next = sp2;
sp2->_prev = sp1; std::cout<<sp1.use_count()<<std::endl;
std::cout<<sp2.use_count()<<std::endl;
}
那么为什么用weak_ptr就可以解决循环引用的问题,简单点的来说:weak_ptr的构造和析构不会引起引用计数的增加或减少.
最后,作为补充:weak_ptr必须与shared_ptr配合使用,不能单独使用.
【C++】智能指针简述(五):解决循环引用的weak_ptr的更多相关文章
- 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr
什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...
- 深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用(上)
深入研究Block捕获外部变量和__block实现原理 前言 在上篇中,仔细分析了一下Block的实现原理以及__block捕获外部变量的原理.然而实际使用Block过程中,还是会遇到一些问题,比如R ...
- swift闭包中解决循环引用的问题
swift中可以通过三种方法解决循环引用的问题 利用类似oc方法解决循环引用weak var weakSelf = self weak var weakSelf = self loadData = { ...
- Flask-分开Models解决循环引用
Flask-分开Models解决循环引用 在之前我们测试中,所有语句都在同一个文件中,但随着项目越来越大,管理起来有所不便,所以将Models分离.基本的文件结构如下 \—–app.py\—–mode ...
- 【C++】智能指针简述(六):智能指针总结及补充
本文我们主要来总结一下前文介绍过的智能指针相关原理及实现,顺便补充一下前文未提到的shared_ptr删除器部分的内容. 总结: 1.智能指针,通过RAII机制,构造对象时完成资源的初始化,析构对象时 ...
- block为什么用copy以及如何解决循环引用
在完成项目期间,不可避免的会使用到block,因为block有着比delegate和notification可读性更高,而且看起来代码也会很简洁.于是在目前的项目中大量的使用block. 之前给大家介 ...
- 如何在 iOS 中解决循环引用的问题
稍有常识的人都知道在 iOS 开发时,我们经常会遇到循环引用的问题,比如两个强指针相互引用,但是这种简单的情况作为稍有经验的开发者都会轻松地查找出来. 但是遇到下面这样的情况,如果只看其实现代码,也很 ...
- Swift-闭包使用及解决循环引用问题
Swift中闭包使用参考OC中block使用,基本一致 // 闭包类型 首先写(参数列表)->(返回值类型) func loadData(callBack : (jsonData:String) ...
- 第八章 springboot + mybatis + 多数据源2(解决循环引用)
解决了循环引用 1.application.properties #the first datasource jdbc.names:1,2 jdbc1.driverClassName = com.my ...
随机推荐
- IntelliJ IDEA在行尾增加分号
IntelliJ IDEA在行尾增加分号 Ctrl+Shift+Enter - 本身的含义是自动完成,如果需要的话,会在行尾添加分号:
- win7开启超级管理员账户(Administrator)
win7开启超级管理员账户(Administrator) 不同于XP系统,Windows7系统据说出于安全的考虑,将超级管理员帐户"Administrator"在登陆界面给隐藏了, ...
- CodeIgniter 向mysql插入数据包括字母、汉字问题
今天在使用ci框架,须要向mysql数据表插入数据.当中的一个字段包括汉字.字母.但是用传统的使用sql语句:insert into XXX这样的方式,不管怎样都插入不成功,最后我换了还有一种方式: ...
- for in、for和EnumerateObjectsUsingBlock遍历的区别
1.对于集合中对象数很多的情况下,for in 的遍历速度非常之快,但小规模的遍历并不明显(还没普通for循环快) 2. 如果在for in 循环里,对这个数组进行了修改的话,无论是增,删,修改数组元 ...
- MySQL具体解释(21)------------缓存參数优化
数据库属于 IO 密集型的应用程序.其主要职责就是数据的管理及存储工作. 而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所以,要优 ...
- simple-framework(MaliSDK框架分析)
simple-framework(Mali SDK框架分析) 1.全部的定义及实现放在同一个命名空间中.文件包括#include一般在命名空间的外面. 总的命名空间为namespace MaliSDK ...
- 十分简便的APK反编译(Mac 版本号 具体解释)
之前參考了网上大神们介绍的apk for mac 的反编译的文章,里面写的十分具体而有用,可是因为apk for mac中反编译细节十分繁琐,过程也相对照较复杂,针对这个缺陷本人对其反编译的过程进行 ...
- go1
关键字: break default func interface select case defer go map struct chan else goto package switch cons ...
- NPOI设置Excel中的单元格识别为日期
只有月/日/年的格式,才能显示为Date 其他的,都是显示为Custom
- ModuleNotFoundError: No module named 'urlparse'
这是2.x转3.x问题 2.x写法: from urlparse import urlparse 3.x写法: from urllib.parse import urlparse 问题解决.