C++11:shared_ptr循环引用问题

一、shared_ptr的弊端 

struct Listnode
{int _val;std::shared_ptr<Listnode> _prev;std::shared_ptr<Listnode> _next;Listnode(int val ):_val(val),_prev(nullptr),_next(nullptr){}~Listnode(){cout << "~Listnode()" << endl;}
};
int main()
{std::shared_ptr<Listnode> n1(new Listnode(20));std::shared_ptr<Listnode> n2(new Listnode(10));n1->_next = n2; n2->_prev = n1;return 0;
}

 如上的情况就出现了循环引用,两个对象相互掣肘。

1. node1和node2两个智能指针对象指向两个节点,引用计数变成1,我们不需要手动delete。
2. node1的_next指向node2,node2的_prev指向node1,引用计数变成2。
3. node1和node2析构,引用计数减到1,但是_next还指向下一个节点。但是_prev还指向上一个节点。
4. 也就是说_next析构了,node2就释放了。
5. 也就是说_prev析构了,node1就释放了。
6. 但是_next属于node的成员,node1释放了,_next才会析构,而node1由_prev管理,_prev属于node2成员,所以这就叫循环引用,谁也不会释放。
展开来讲:

两个对象的引用计数都变为2,当要进行析构时就陷入了循环引用。

1、左边节点要想析构就得等右边的_prev去调用析构。

2、右边节点被delete时去调用_prev.

3、而右边节点被析构需要左边节点的_next去调用析构

4、左边节点被delete时去调用_prev

5、左边节点要想析构就得等右边的_prev去调用析构。

到这里就以及死循环了。

二、weak

它的特点就是不增加引用计数,专门用于shared_ptr出现循环引用的情况。

struct Listnode
{int _val;std::weak_ptr<Listnode> _prev;std::weak_ptr<Listnode> _next;Listnode(int val ):_val(val){}~Listnode(){cout << "~Listnode()" << endl;}
};
int main()
{std::shared_ptr<Listnode> n1(new Listnode(20));std::shared_ptr<Listnode> n2(new Listnode(10));n1->_next = n2; n2->_prev = n1;return 0;
}

 2.1模拟实现

struct Listnode
{int _val;gaz::weak_ptr<Listnode> _prev;gaz::weak_ptr<Listnode> _next;Listnode(int val ):_val(val){}~Listnode(){cout << "~Listnode()" << endl;}
};
int main()
{gaz::shared_ptr<Listnode> n1(new Listnode(20));gaz::shared_ptr<Listnode> n2(new Listnode(10));n1->_next = n2; n2->_prev = n1;return 0;
}
template<class T>class weak_ptr{public://RALLweak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptr<T>& sp){_ptr = sp.get();}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/660632.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Macos M3 FastGpt部署实现文档问答

前言 经过 Macos安装OrbStack-CSDN博客 Centos8安装docker-compose-CSDN博客 两篇文章的铺垫&#xff0c;可以正式在mac m芯片系列的电脑上使用docker安装项目了 什么是FastGpt FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模…

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(七)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 14 节&#xff09; P14《13.ArkUI组件-自定义组件》 将可变部分封装成组件的成员变量&#xff1a; 1、首先给标题添加两个图标&am…

计算机网络4——网络层4内部路由选择协议

文章目录 一、有关路由选择协议的几个基本概念1、理想的路由算法2、分层次的路由选择协议 二、内部网关协议 RIP1、协议 RIP 的工作原理2、特点3、距离向量算法4、坏消息传播慢 三、内部网关协议 OSPF1、基本特点2、OSPF 的五种分组类型 本节将讨论几种常用的路由选择协议&…

chrome和drive安装包路径

Chrome for Testing availability (googlechromelabs.github.io) 下载Stable下面的包哈

Mysql从入门到精通——Mysql知识点总结(基础篇)

参考视频 黑马程序员 MySQL数据库入门到精通i 题单推荐 入门 进阶 SQL语句类型 DDL:数据定义语言&#xff0c;用来定义数据库对象(数据库&#xff0c;表&#xff0c;字段)DML:数据操作语言&#xff0c;对数据库表中的数据进行增删改DQL:数据查询语言,用来查询数据库中表的…

音视频入门基础:像素格式专题(1)——RGB简介

一、像素格式简介 像素格式&#xff08;pixel format&#xff09;指像素色彩按分量的大小和排列。这种格式以每个像素所使用的总位数以及用于存储像素色彩的红、绿、蓝和 alpha 分量的位数指定。在音视频领域&#xff0c;常用的像素格式包括RGB格式和YUV格式&#xff0c;本文…

罗宾斯《管理学》第13版/教材讲解/考研真题视频课程/网课

本课程是罗宾斯《管理学》&#xff08;第13版&#xff09;精讲班&#xff0c;为了帮助参加研究生招生考试指定考研参考书目为罗宾斯《管理学》&#xff08;第13版&#xff09;的考生复习专业课&#xff0c;我们根据教材和名校考研真题的命题规律精心讲解教材章节内容。 序号名…

ubuntu部署sonar与windows下使用sonar-scanner

ubuntu部署sonar与windows下使用sonar-scanner sonar部署java安装mysql安装配置sonarqube 插件安装sonar-scanner使用简单使用 sonar部署 使用的是sonarqube-7.5&#xff0c;支持的java环境是jdk8&#xff0c;且MySQL版本 >5.6 && <8.0 java安装 打开终端&…

白话机器学习2:快速理解不同分类模型

一、支持向量机(SVM) 想象你在桌子上有一堆苹果和橘子&#xff0c;你的任务是用一根棍子&#xff08;在二维空间里&#xff0c;这根棍子就是一条直线&#xff09;把它们分开。苹果在棍子的一边&#xff0c;橘子在棍子的另一边。这就是分类问题的基本形式&#xff0c;而SVM就是用…

首页最新 多IP浏览器防关联:如何配置多个独立且稳定的IP地址?

在互联网时代&#xff0c;IP地址的重要性不言而喻。然而&#xff0c;IP关联问题却成为一项令人担忧的隐私和安全挑战。针对这个问题&#xff0c;多IP浏览器是一种解决方案&#xff0c;可以帮助用户单独配置多个独立且稳定的IP地址&#xff0c;有效地防止IP关联。 一、IP关联是…

品牌百度百科词条需要什么资料?

品牌百度百科词条是一个品牌的数字化名片&#xff0c;更是品牌历史、文化、实力的全面展现。 作为一个相当拿得出手的镀金名片&#xff0c;品牌百度百科词条创建需要什么资料&#xff0c;今天伯乐网络传媒就来给大家讲解一下。 一、品牌基本信息&#xff1a;品牌身份的明确 品…

关于Centos 7/8 网络设置 与工具连接

网络三步曲的配置 1、首先更改虚拟机的网络配置 查看子网地址以及网关 如果有要求需要更改IP地址&#xff0c;规定第三位是指定数值&#xff0c;那么需要全部更改 例如&#xff0c;IP地址为192.168.200.30 其中200为重点&#xff0c;更改时为以下步骤 1、点击DHCP设置&#x…