c++介绍智能指针 十二(2)
智能指针share_ptr,与unique_ptr不同,多个shar_ptr对象可以共同管理一个指针,它们通过一个共同的引用计数器来管理指针。当一个智能指针对象销毁时,计数器减一。当计数器为0时,会将所指向的内存对象释放。
#include<memory>
#include<iostream>
#include<vector>
#include<algorithm>
#include<chrono>
using namespace std;class Rectangle {public:Rectangle(double w, double h) :width(w), height(h) {}~Rectangle() {}double area(){return width * height;}
private:double width;double height;
};
int main()
{using std::shared_ptr;shared_ptr<Rectangle>p1(new Rectangle(1, 5));shared_ptr<Rectangle>p2 = p1;shared_ptr<Rectangle>p3(p2);cout << p1.use_count() << endl;
}
打印结果 

另外share_ptr提供几个辅助函数,用于对封装指针类型得静态转换,动态转换以及常量转换,它们分别是dynamic_pointer_cast,static_pointer_cast和const_point_cast.
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class Base {
public:virtual ~Base() {}};
class Derive :public Base {};int main()
{shared_ptr<Base>sp1(new Derive());shared_ptr<Derive>sp2 = dynamic_pointer_cast<Derive>(sp1);shared_ptr<Base>sp3 = static_pointer_cast<Base>(sp2);cout << "use count:" << sp1.use_count() << endl;
虽然他们封装得对象类型不同,但他们都是指向同一个对象,所以引用计数为3.
在使用share_ptr时容易出现一个问题,就是当出现循环引用时,无法释放所指向的资源。造成内存泄漏。
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class Person
{
public:Person(string name) :m_name(name) { cout << m_name << "constructed" << endl;}~Person(){cout << m_name << "desconstructed" << endl;}void setParter(const shared_ptr<Person>& other){m_partner = other;}
private:string m_name;shared_ptr<Person>m_partner;
};int main()
{vector<shared_ptr<Person>>people;people.push_back(shared_ptr<Person>(new Person("张三")));people.push_back(shared_ptr<Person>(new Person("李四")));people.push_back(shared_ptr<Person>(new Person("王五")));people[0]->setParter(people[1]);people[1]->setParter(people[2]);people[2]->setParter(people[0]);return 0;
}
打印结果
这里people存放了三个person对象,由于person 的成员变量m_partner也是指向Person对象的共享智能指针,接下来这三条语句,peoeple中的第一个元素的m_partner指向了第二个元素中的Person对象,第二个元素的m_partner指向了第三个元素中Person的对象,第三个元素的m_partner指向了第一个元素中的Person对象。这样每个对象的引用计数都是2.当people向量离开作用域销毁后,会将每个对象的引用计数减1,但每个对象的成员m_partner仍存在,所以无法删除Person对象,最终导致内存的泄露。为了防止这种情况出现,就避免出现share_ptr循环引用情况。或者结合使用另外一种智能指针weak_ptr;例如将Person成员变量中的share_ptr改为weak_ptr,当peolple离开作用域销毁后,他所指向的对象也都自动销毁。
weak_ptr不能单独使用,需要结合share_ptr一起使用。我weak_ptr的对象可以将share_ptr作为构造函数的参数初始化,或者定义一个空的weak_ptr,然后将share_ptr对象赋值给它。如下代码
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class A {};
int main()
{shared_ptr<A> sp1 = make_shared<A>();weak_ptr<A>wp1(sp1);weak_ptr<A>wp2;wp2 =sp1;cout << "use count: " << wp2.use_count() << endl;}
打印结果
weak_ptr的主要特征是,只对share_ptr所管理的的对象进行观测,不会改变对象的引用计数。如下代码
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class Rectangle {public:Rectangle(double w, double h) :width(w), height(h) {}~Rectangle() {}double area(){return width * height;}
private:double width;double height;
};
int main()
{weak_ptr<Rectangle>w_sp1;{shared_ptr<Rectangle>sp1(new Rectangle(1, 2));shared_ptr<Rectangle>sp2 = sp1;w_sp1 = sp2;cout << "作用域内部usecount=" << w_sp1.use_count() << endl;}cout << "作用域外部usercount=" << w_sp1.use_count() << endl;cout << "expired=" << w_sp1.expired() << endl;//为1时所观测的对象不可用
}
打印结果
我们可以通过weak_ptr使用lock函数来获得一个shared_ptr以获得封装对象的控制权。在下面这个例子里我们输出share_ptr里封装对象指针,由于share_ptr重载了插入运算符,所以可以直接打印出封装的指针的值。
#include<memory>
#include<iostream>
#include<vector>
using namespace std;
class Rectangle {public:Rectangle(double w, double h) :width(w), height(h) {}~Rectangle() {}double area(){return width * height;}
private:double width;double height;
};
int main()
{weak_ptr<Rectangle>w_sp1;{shared_ptr<Rectangle>sp1(new Rectangle(1, 2));shared_ptr<Rectangle>sp2 = sp1;w_sp1 = sp2;shared_ptr<Rectangle>sp3 = w_sp1.lock();cout << "作用域内部sp3=" << sp3 << endl;}shared_ptr<Rectangle>sp3 = w_sp1.lock();cout << "作用域外部sp3=" << sp3 << endl;cout << "expired=" << w_sp1.expired() << endl;//为1时所观测的对象不可用
}
打印结果
可以看到在作用域里面share_ptr是个有效指针,而在作用域外是个空指针。所以当我们使用weak_ptr观察对象是否为空指针时,并不需要使用use_count或expired来判断 ,而是可以直接调用lock函数获得一个share_ptr对象,如果share_ptr包含的指针非空那么就可用。由于lock对象是个原子操作,是一个不可分割的操作,当原子操作执行进程中时,其它线程不能读取,修改或者中断操作的数据,因此,使用lock函数保证了多线程时获得的share_ptr中的对象是安全有效的,此外,在多线程环境下,当使用expired函数时,只有当expired返回true时才是有意义的。
下面时weak_ptr和share_ptr直接的关系。

相关文章:
c++介绍智能指针 十二(2)
智能指针share_ptr,与unique_ptr不同,多个shar_ptr对象可以共同管理一个指针,它们通过一个共同的引用计数器来管理指针。当一个智能指针对象销毁时,计数器减一。当计数器为0时,会将所指向的内存对象释放。 #include<memory>…...
西门子S7-1200 PLC远程调试技术方案(巨控GRM532模块)
三步快速实现远程调试 硬件部署 准备西门子S7-1200 PLC、巨控GRM552YW-C模块及编程电脑。GRM552YW-C通过网口与PLC连接,支持4G/5G/Wi-Fi/有线网络接入,无需复杂布线。 软件配置 安装GVCOM3配置软件,注册模块(输入唯一序列号与密…...
vue启动 localhost无法访问
1. localhost 和 127.0.0.1 虽然都指向本机,但它们有细微的区别: - localhost 是一个域名,需要通过 DNS 解析或本地 hosts 文件解析为 IP 地址 - 127.0.0.1 是直接的 IP 地址,不需要解析过程 2. 无法访问 localhost 的可…...
Mac上更改默认应用程序
Mac上为某些文件设置默认打开应用的时候,刚开始是通过打开方式,其他里面,勾选始终以此方式打开,但实际上这个功能并不太好用,经常会让人误以为已经设置好了。但是实际上只是在当前目录起作用。真正解决这个问题可以按照…...
【开源+代码解读】Search-R1:基于强化学习的检索增强大语言模型框架3小时即可打造个人AI-search
大语言模型(LLMs)在处理复杂推理和实时信息检索时面临两大挑战:知识局限性(无法获取最新外部知识)和检索灵活性不足(传统方法依赖固定检索流程)。现有方法如检索增强生成(RAG)和工具调用(Tool-Use)存在以下问题: RAG:单轮检索导致上下文不足,无法适应多轮交互场景…...
贪心算法和遗传算法优劣对比——c#
项目背景:某钢管厂的钢筋原材料为 55米,工作需要需切割 40 米(1段)、11 米(15 段)等 4 种规格 ,现用贪心算法和遗传算法两种算法进行计算: 第一局:{ 40, 1 }, { 11, 15…...
网络安全防护总体架构 网络安全防护工作机制
1 实践内容 1.1 安全防范 为了保障"信息安全金三角"的CIA属性、即机密性、完整性、可用性,信息安全领域提出了一系列安全模型。其中动态可适应网络安全模型基于闭环控制理论,典型的有PDR和P^2DR模型。 1.1.1 PDR模型 信息系统的防御机制能…...
SpringCloud带你走进微服务的世界
认识微服务 随着互联网行业的发展,对服务的要求也越来越高,服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢? 单体架构 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部…...
Python设计模式 - 建造者模式
定义 建造者模式是一种创建型设计模式,主要用于构建包含多个组成部分的复杂对象。它将对象的构建过程与表示分离,使得同样的构建过程可以创建不同的对象表示。 结构 抽象建造者(Builder):声明创建产品的各个部件的方…...
在 Ubuntu 上安装和配置 Docker 的完整指南
Docker 是一个开源的平台,旨在简化应用程序的开发、部署和运行。通过将应用程序及其依赖项打包到容器中,Docker 确保应用程序可以在任何环境中一致地运行。 目录 前言安装前的准备安装 Docker 步骤 1:更新包索引步骤 2:安装必要…...
网络安全之数据加密(DES、AES、RSA、MD5)
刚到公司时,我的工作就是为app端提供相应的接口。之前app使用的是PHP接口,对数据加密方面做得比较少。到使用java接口时,老大开始让我们使用DES加密,进行数据传输,但是后来觉得DES是对称加密,密钥存在客户端…...
基于SpringBoot的“校园周边美食探索及分享平台”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“校园周边美食探索及分享平台”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 校园周边美食探索及分享平台结构图…...
vscode关闭仓库后如何打开
vscode源代码管理->更改->代码 关闭仓库后如何打开。 关闭仓库操作 打开仓库操作 1.按下 Ctrl Shift P(Windows/Linux)或 Cmd Shift P(Mac)打开命令面板。 2.在命令面板中输入 Git: Open Repository,然后选…...
Node.js Web 模块详解
Node.js Web 模块详解 引言 Node.js作为一款流行的JavaScript运行环境,以其高性能、事件驱动和非阻塞I/O模型而闻名。在Node.js中,模块是构建应用程序的基础,也是其强大的关键所在。本文将详细介绍Node.js的Web模块,包括其基本概…...
DeepSeek-R1 论文阅读总结
1. QA问答(我的笔记) Q1: DeepSeek如何处理可读性问题? 通过构建冷启动数据(数千条长CoT数据)微调基础模型,结合多阶段训练流程(RL训练、拒绝采样生成SFT数据),并优化输…...
scoop退回软件版本的方法
title: scoop退回软件版本的方法 date: 2025-3-11 23:53:00 tags: 其他 前言 在软件更新后,如果出现了很影响使用体验的问题,那么可以把软件先退回以前的版本进行使用, 但是scoop本身并没有提供直接让软件回退版本的功能,因此…...
Linux 》》Ubuntu 18 LTS 之后的版本 修改IP地址 主机名
进入目录 /etc/netplan 修改 50-cloud-init.yaml 》保存文件后,执行以下命令应用更改: sudo netplan apply 》》 DHCP模式 修改主机名 hostnamectl set-hostname xxxx 修改cloud.cfg 防止重启主机名还原 但测试下来 不修改, 重启 也不会还…...
泰山派开发之—Ubuntu24.04下Linux开发环境搭建
简介 最近翻到了吃灰已久的泰山派,是刚出来的时候用优惠券买的,当时价格挺便宜的,最近给它翻出来了,打算试试做个项目。买的泰山派容量是2G16G,SOC芯片使用的是RK3566,搭载1TOP算力的NPU,并且具…...
哈尔滨算力服务器托管推荐-青蛙云
哈尔滨年平均气温3.5摄氏度,有发展云计算和算力数据中心的天然优势 ,今天为哈尔滨算力服务器托管服务商:青蛙云,黑龙江经营17年的老牌IDC服务商。 先来了解下算力服务器: 算力服务器,尤其是那些用于运行人…...
openharmony体验
openharmony5 去年已经出来了 如果以前做过android开发的,学起来不难,关键 1:环境 DevEco Studio 5.0.3 Beta2 https://developer.huawei.com/consumer/cn/deveco-studio/ win10_64bit CPU amd64(不是arm的) 2:安装 执行EXE 安装就行&#x…...
[Ai 力扣题单] 数组基本操作篇 27/704/344/386
题单分类:DeepSeek刷力扣辅助题单 存留记录-CSDN博客 27 27. 移除元素 - 力扣(LeetCode) 这道题就一个点 1.数组在内存上连续 所以要么赋值覆盖,要么移动覆盖,但是它要求了前 k 个元素 所以只能移动覆盖 所以我有了如下思考过程: 3223 , 3举例 如果是…...
⭐算法OJ⭐汉明距离【位操作】(C++ 实现)Hamming Distance
Hamming Distance(汉明距离)是用于衡量两个等长字符串在相同位置上不同字符的个数的度量。它通常用于比较两个二进制字符串或编码序列的差异。 定义 给定两个长度相同的字符串 A A A 和 B B B,它们的汉明距离 D ( A , B ) D(A,B) D(A,B)…...
了解一下HTTP的短连接和长连接
在 HTTP 协议中,连接的方式主要分为长连接和短连接。这两种连接方式的主要区别在于连接的生命周期和数据传输的效率。理解它们的差异对于优化 Web 应用的性能和资源利用至关重要。以下是 HTTP 长连接和短连接的详细解释。 1. 短连接(HTTP/1.0࿰…...
蓝桥杯刷题 Day1 高精度加法
蓝桥杯刷题 Day1 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 蓝桥杯刷题 Day1前言一、大数加法1. 解题思路2. 代码2.1主函数2.2 去除前导02.3 大数相加2.4 完整代码 二、KMP字符串匹配0. 知识点速记1. 解题思路…...
大语言模型的潜力是否被高估
关于大语言模型(LLM)的潜力是否被高估,目前学术界和产业界存在显著分歧。以下从技术能力、应用局限性和未来发展方向三个方面综合分析: 一、技术能力的争议:潜力与局限并存 对现实世界的理解与模拟 MIT的研究表明…...
Linux入门 全面整理终端 Bash、Vim 基础命令速记
Linux入门 2025 超详细全面整理 Bash、Vim 基础命令速记 刚面对高级感满满的 终端窗口是不是有点懵?于是乎,这份手册就是为你准备的高效学习指南!我把那些让人头大的系统设置、记不住的命令都整理成了对你更友好的格式,让你快速学…...
AI智能代码疫苗技术,赋能数字化应用内生安全自免疫
“DevSecOps市占率持续领先,IAST探针覆盖率十倍增长,代码疫苗技术已成功帮助上千家行业用户成功抵御‘Log4j2.x’等重大未知漏洞的利用攻击。”子芽在腾讯专访中透露。 这是2021年悬镜安全交出的一张成绩单。悬镜安全是DevSecOps敏捷安全先行者…...
《SQL性能优化指南:新手如何写出高效的数据库查询
新手程序员如何用三个月成为SQL高手?万字自学指南带你弯道超车 在数据为王的时代,掌握SQL已成为职场新人的必修课。你可能不知道,仅用三个月系统学习,一个零基础的小白就能完成从数据库萌新到SQL达人的蜕变。去年刚毕业的小王就是…...
【PyMySQL】Python操作MySQL
1、安装pymysql pip install pymysql2、导包 import pymysql3、连接MySQL数据库 db pymysql.connect(hostlocalhost # 本地localhost,或服务器IP地址,userroot # 用户名,passwordpassword # 密码,databasemysql) #数据库名4、创建游标 cursor db.cursor()5、增…...
使用RabbitMQ实现流量削峰填谷
原理 流量削峰填谷是指在面对突发的高流量时,通过消息队列将瞬时大量请求暂时存储起来,并逐步处理这些请求,从而避免系统过载。RabbitMQ 作为消息中间件可以很好地支持这一需求,特别是结合其延时消息插件(rabbitmq_de…...
