总结一下前文内容:

  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的更多相关文章

  1. 智能指针 auto_ptr、scoped_ptr、shared_ptr、weak_ptr

    什么是RAII? RAII是Resource Acquisition Is Initialization的简称,是C++语言的一种管理资源.避免泄漏的惯用法. RAII又叫做资源分配即初始化,即:定义 ...

  2. 深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用(上)

    深入研究Block捕获外部变量和__block实现原理 前言 在上篇中,仔细分析了一下Block的实现原理以及__block捕获外部变量的原理.然而实际使用Block过程中,还是会遇到一些问题,比如R ...

  3. swift闭包中解决循环引用的问题

    swift中可以通过三种方法解决循环引用的问题 利用类似oc方法解决循环引用weak var weakSelf = self weak var weakSelf = self loadData = { ...

  4. Flask-分开Models解决循环引用

    Flask-分开Models解决循环引用 在之前我们测试中,所有语句都在同一个文件中,但随着项目越来越大,管理起来有所不便,所以将Models分离.基本的文件结构如下 \—–app.py\—–mode ...

  5. 【C++】智能指针简述(六):智能指针总结及补充

    本文我们主要来总结一下前文介绍过的智能指针相关原理及实现,顺便补充一下前文未提到的shared_ptr删除器部分的内容. 总结: 1.智能指针,通过RAII机制,构造对象时完成资源的初始化,析构对象时 ...

  6. block为什么用copy以及如何解决循环引用

    在完成项目期间,不可避免的会使用到block,因为block有着比delegate和notification可读性更高,而且看起来代码也会很简洁.于是在目前的项目中大量的使用block. 之前给大家介 ...

  7. 如何在 iOS 中解决循环引用的问题

    稍有常识的人都知道在 iOS 开发时,我们经常会遇到循环引用的问题,比如两个强指针相互引用,但是这种简单的情况作为稍有经验的开发者都会轻松地查找出来. 但是遇到下面这样的情况,如果只看其实现代码,也很 ...

  8. Swift-闭包使用及解决循环引用问题

    Swift中闭包使用参考OC中block使用,基本一致 // 闭包类型 首先写(参数列表)->(返回值类型) func loadData(callBack : (jsonData:String) ...

  9. 第八章 springboot + mybatis + 多数据源2(解决循环引用)

    解决了循环引用 1.application.properties #the first datasource jdbc.names:1,2 jdbc1.driverClassName = com.my ...

随机推荐

  1. IntelliJ IDEA在行尾增加分号

    IntelliJ IDEA在行尾增加分号 Ctrl+Shift+Enter - 本身的含义是自动完成,如果需要的话,会在行尾添加分号:

  2. win7开启超级管理员账户(Administrator)

    win7开启超级管理员账户(Administrator) 不同于XP系统,Windows7系统据说出于安全的考虑,将超级管理员帐户"Administrator"在登陆界面给隐藏了, ...

  3. CodeIgniter 向mysql插入数据包括字母、汉字问题

    今天在使用ci框架,须要向mysql数据表插入数据.当中的一个字段包括汉字.字母.但是用传统的使用sql语句:insert into XXX这样的方式,不管怎样都插入不成功,最后我换了还有一种方式: ...

  4. for in、for和EnumerateObjectsUsingBlock遍历的区别

    1.对于集合中对象数很多的情况下,for in 的遍历速度非常之快,但小规模的遍历并不明显(还没普通for循环快) 2. 如果在for in 循环里,对这个数组进行了修改的话,无论是增,删,修改数组元 ...

  5. MySQL具体解释(21)------------缓存參数优化

    数据库属于 IO 密集型的应用程序.其主要职责就是数据的管理及存储工作. 而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所以,要优 ...

  6. simple-framework(MaliSDK框架分析)

    simple-framework(Mali SDK框架分析) 1.全部的定义及实现放在同一个命名空间中.文件包括#include一般在命名空间的外面. 总的命名空间为namespace MaliSDK ...

  7. 十分简便的APK反编译(Mac 版本号 具体解释)

    之前參考了网上大神们介绍的apk for mac  的反编译的文章,里面写的十分具体而有用,可是因为apk for mac中反编译细节十分繁琐,过程也相对照较复杂,针对这个缺陷本人对其反编译的过程进行 ...

  8. go1

    关键字: break default func interface select case defer go map struct chan else goto package switch cons ...

  9. NPOI设置Excel中的单元格识别为日期

    只有月/日/年的格式,才能显示为Date 其他的,都是显示为Custom

  10. ModuleNotFoundError: No module named 'urlparse'

    这是2.x转3.x问题 2.x写法: from urlparse import urlparse   3.x写法: from urllib.parse import urlparse 问题解决.