C++ shared_ptr

shared_ptr共享它指向的对象,多个shared_ptr可以指向(关联)相同的对象,在内部采用计数机制来实现。
当新的shared_ptr与对象关联时,引用计数增加1。
当shared_ptr超出作用域时,引用计数减1。当引用计数变为0时,则表示没有任何shared_ptr与对象关联,则释放该对象。

一、基本用法

shared_ptr的构造函数也是explicit,但是,没有删除拷贝构造函数和赋值函数。

1)初始化

方法一:
shared_ptr p0(new AA(“西施”)); // 分配内存并初始化。
方法二:
shared_ptr p0 = make_shared(“西施”); // C++11标准,效率更高。
shared_ptr pp1=make_shared(); // 数据类型为int。
shared_ptr pp2 = make_shared(); // 数据类型为AA,默认构造函数。
shared_ptr pp3 = make_shared(“西施”); // 数据类型为AA,一个参数的构造函数。
shared_ptr pp4 = make_shared(“西施”,8); // 数据类型为AA,两个参数的构造函数。
方法三:
AA* p = new AA(“西施”);
shared_ptr p0§; // 用已存在的地址初始化。
方法四:
shared_ptr p0(new AA(“西施”));
shared_ptr p1(p0); // 用已存在的shared_ptr初始化,计数加1。
shared_ptr p1=p0; // 用已存在的shared_ptr初始化,计数加1。

2)使用方法

智能指针重载了*和->操作符,可以像使用指针一样使用shared_ptr。
use_count()方法返回引用计数器的值。
unique()方法,如果use_count()为1,返回true,否则返回false。
shared_ptr支持赋值,左值的shared_ptr的计数器将减1,右值shared_ptr的计算器将加1。
get()方法返回裸指针。
不要用同一个裸指针初始化多个shared_ptr。
不要用shared_ptr管理不是new分配的内存。

3)用于函数的参数

与unique_ptr的原理相同。

4)不支持指针的运算(+、-、++、–)

二、更多细节

1)将一个unique_ptr赋给另一个时,如果源unique_ptr是一个临时右值,编译器允许这样做;如果源unique_ptr将存在一段时间,编译器禁止这样做。一般用于函数的返回值。
2)用nullptr给shared_ptr赋值将把计数减1,如果计数为0,将释放对象,空的shared_ptr==nullptr。
3)release()释放对原始指针的控制权,将unique_ptr置为空,返回裸指针。
4)std::move()可以转移对原始指针的控制权。还可以将unique_ptr转移成shared_ptr。
5)reset()改变与资源的关联关系。
pp.reset(); // 解除与资源的关系,资源的引用计数减1。
pp. reset(new AA(“bbb”)); // 解除与资源的关系,资源的引用计数减1。关联新资源。
6)swap()交换两个shared_ptr的控制权。
void swap(shared_ptr &_Right);
7)shared_ptr也可象普通指针那样,当指向一个类继承体系的基类对象时,也具有多态性质,如同使用裸指针管理基类对象和派生类对象那样。
8)shared_ptr不是绝对安全,如果程序中调用exit()退出,全局的shared_ptr可以自动释放,但局部的shared_ptr无法释放。
9)shared_ptr提供了支持数组的具体化版本。
数组版本的shared_ptr,重载了操作符[],操作符[]返回的是引用,可以作为左值使用。
10)shared_ptr的线程安全性:
shared_ptr的引用计数本身是线程安全(引用计数是原子操作)。
多个线程同时读同一个shared_ptr对象是线程安全的。
如果是多个线程对同一个shared_ptr对象进行读和写,则需要加锁。
多线程读写shared_ptr所指向的同一个对象,不管是相同的shared_ptr对象,还是不同的shared_ptr对象,也需要加锁保护。
11)如果unique_ptr能解决问题,就不要用shared_ptr。unique_ptr的效率更高,占用的资源更少。
示例1:

#include <iostream>
#include <memory>
using  namespace std;class AA
{
public:string m_name;AA() { cout << m_name << "调用构造函数AA()。\n"; }AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }
};int main()
{shared_ptr<AA> pa0(new AA("西施a"));     // 初始化资源西施a。shared_ptr<AA> pa1 = pa0;                       // 用已存在的shared_ptr拷贝构造,计数加1。shared_ptr<AA> pa2 = pa0;                       // 用已存在的shared_ptr拷贝构造,计数加1。cout << "pa0.use_count()=" << pa0.use_count() << endl;   // 值为3。shared_ptr<AA> pb0(new AA("西施b"));    // 初始化资源西施b。shared_ptr<AA> pb1 = pb0;                      // 用已存在的shared_ptr拷贝构造,计数加1。cout << "pb0.use_count()=" << pb0.use_count() << endl;   // 值为2。pb1 = pa1;      // 资源西施a的引用加1,资源西施b的引用减1。pb0 = pa1;      // 资源西施a的引用加1,资源西施b的引用成了0,将被释放。cout << "pa0.use_count()=" << pa0.use_count() << endl;   // 值为5。cout << "pb0.use_count()=" << pb0.use_count() << endl;   // 值为5。
}

推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家:
零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/Linux内核)
https://xxetb.xet.tech/s/3Zqhgt

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

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

相关文章

YOLOv8改进 | 注意力机制 | 添加适用于遥感图像的LSKblock注意力——【二次创新+完整代码】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡 遥感目标检测的研究主要集中在改进方向边界框的表示上,而忽略了遥感场景中独特的先验知识。 这类先验知识对于准确检测微小目标至关重要,因为这些目标往往需要更大的上下文信息才能被正确识别。提出的 LSKNet …

根据身份证获取生日、性别、年龄

当type1时获取出生日期,type2时获取性别,type3时获取年龄 /** 当type1时获取出生日期,type2时获取性别,type3时获取年龄* */ function IdCard(IdCard, type) {if (type 1) {//获取出生日期let birthday IdCard.substring(6, 10) "-" IdCard.substring(10, 12) …

正式环境下的历史数据迁移方案,你知道几个?

一、历史数据库 MySQL 数据库可以很好地支撑海量的 OLTP(Online Transaction Processing)的系统,但是对于海量的互联网业务来说,数据量是非常巨大的。 假设一天 10 亿笔交易,每笔交易至少需要有一条记录,用于记录该笔交易,这就是通常所谓的流水数据。再假设一笔流水占…

C++100行超简单系统

非常好用&#xff0c;小白也可以自己修改 先来看图片&#xff1a; 用法附在代码里了&#xff01; #include <bits/stdc.h> #include <windows.h>using namespace std;struct users {string name;string num; bool f; } u[10000];int now_users 0; /*当前用户数*…

springboot接入springai-openAi代理和智谱ai调用示例

这里写自定义目录标题 背景配置具体代码总结 背景 一说到调用openAI的api或者做一些小项目&#xff0c;大部分例子都是python或者node实现的&#xff0c;后来发现spring出了对于openai的支持框架&#xff0c;所以尝试用一用。这里是SpringAI的地址&#xff0c;有兴趣的可以去官…

20240615在WIN11下的串口调试助手的下载安装以及使用

20240615在WIN11下的串口调试助手的下载安装以及使用 2024/6/15 18:06 百度&#xff1a;串口调试助手 blob:https://apps.microsoft.com/df934d29-fd7a-4873-bb6b-a4ab5a7934c9 串口调试助手 Installer.exe 收发的LOG&#xff1a; rootok3588:/# ./uart_test /dev/ttyS0 11520…

反射,枚举以及lambda表达式

【本节目标】 1. 掌握反射 2. 掌握枚举 3. 掌握lambda表达式使用 反射 1 定义 Java的反射&#xff08;reflection&#xff09;机制是在运行状态中&#xff0c;对于任意一个类&#xff0c;都能够知道这个类的所有属性和方法&#xff1b;对于任意一个对象&#xff0c;都能够调…

C++ bfS

岛屿的最大面积 . - 力扣&#xff08;LeetCode&#xff09; 1.刚开始mn又加了int 2.bfs里符合条件了&#xff0c;不push&#xff0c;&#xff0c;&#xff0c;在写什么几把 class Solution { public:int dx[4] {0, 0, 1, -1};int dy[4] {1, -1, 0, 0};bool vis[50][50];int…

从零制作一个ubuntu的docker镜像

上次分享了一下怎么制作centos的镜像&#xff0c;今天给大家分享一下ubuntu的制作方法。 准备ubuntu环境 如果你有Ubuntu环境的话最好&#xff0c;可以直接打包&#xff0c;我用的是CentOS系统&#xff0c;所以需要借助debootstrap工具。 yum -y install epel-release yum -y…

【博士每天一篇文献-算法】Progressive Neural Networks

阅读时间&#xff1a;2023-12-12 1 介绍 年份&#xff1a;2016 作者&#xff1a;Andrei A. Rusu,Neil Rabinowitz,Guillaume Desjardins,DeepMind 研究科学家,也都是EWC(Overcoming catastrophic forgetting in neural networks)算法的共同作者。 期刊&#xff1a; 未录用&am…

调教LLaMA类模型没那么难,LoRA将模型微调缩减到几小时

简介&#xff1a; 调教LLaMA类模型没那么难&#xff0c;LoRA将模型微调缩减到几小时 LoRA 微调方法&#xff0c;随着大模型的出现而走红。 最近几个月&#xff0c;ChatGPT 等一系列大语言模型&#xff08;LLM&#xff09;相继出现&#xff0c;随之而来的是算力紧缺日益严重。虽…

python如何对list求和

如何在Python中对多个list的对应元素求和&#xff0c;前提是每个list的长度一样。比如&#xff1a;a[1&#xff0c;2&#xff0c;3]&#xff0c;b[2&#xff0c;3&#xff0c;4]&#xff0c;c[3&#xff0c;4&#xff0c;5]&#xff0c;对a&#xff0c;b&#xff0c;c的对应元素…

C语言运算中的临时匿名变量

一&#xff1a;C语言和汇编的区别&#xff08;汇编对应机器操作&#xff0c;C语言对应逻辑操作&#xff09; &#xff08;1&#xff09;C语言叫高级语言&#xff0c;汇编语言叫低级语言 &#xff08;2&#xff09;低级语言的意思是汇编语言和机器操作相对应&#xff0c;汇编语言…

Linux echo输出命令以及重定向符号

echo命令 使用他可以输出指定内容&#xff0c;和编程语言中的 print( )差不多&#xff0c;都是将文字打印输出&#xff0c;该命令无参数。 输出文本 echo "123" 123输出命令执行结果 echo pwd /home/dpc重定向符 > 将左侧的命令结果&#xff0c;覆盖写入右侧…

分数计算 初级题目

今天继续更题。今天的题目是《第五单元 分数的加减法》初级题目。 定位&#xff1a;题目较为初级&#xff0c;适合预习 参考答案&#xff1a;CACCADACAABACBBCDBCB

Linux文件系统【真的很详细】

目录 一.认识磁盘 1.1磁盘的物理结构 1.2磁盘的存储结构 1.3磁盘的逻辑存储结构 二.理解文件系统 2.1如何管理磁盘 2.2如何在磁盘中找到文件 2.3关于文件名 哈喽&#xff0c;大家好。今天我们学习文件系统&#xff0c;我们之前在Linux基础IO中研究的是进程和被打开文件…

【DevOps】 什么是容器 - 一种全新的软件部署方式

目录 引言 一、什么是容器 二、容器的工作原理 三、容器的主要特性 四、容器技术带来的变革 五、容器技术的主要应用场景 六、容器技术的主要挑战 七、容器技术的发展趋势 引言 在过去的几十年里,软件行业经历了飞速的发展。从最初的大型机时代,到后来的个人电脑时代,…

「前端+鸿蒙」鸿蒙应用开发-ArkTS语法说明-组件声明

ArkTS 是鸿蒙应用开发中的一个框架,它允许开发者使用 TypeScript 语法来创建声明式的用户界面。在 ArkTS 中,组件声明是构建 UI 的基础。以下是 ArkTS 快速入门的指南,包括组件声明的语法说明和示例代码。 ArkTS 快速入门 - 语法说明 - 组件声明 组件基础 在 ArkTS 中,组…

【Mongodb-01】Mongodb亿级数据性能测试和压测

mongodb数据性能测试 一&#xff0c;mongodb数据性能测试1&#xff0c;mongodb数据库创建和索引设置2&#xff0c;线程池批量方式插入数据3&#xff0c;一千万数据性能测试4&#xff0c;两千万数据性能测试5&#xff0c;五千万数据性能测试6&#xff0c;一亿条数据性能测试7&am…

Rust 的编译时间过长

Rust 代码的编译时间可能会比某些其他编程语言长&#xff0c;原因有以下几点&#xff1a; Rust 使用了静态类型&#xff0c;这意味着编译器需要更多的时间来验证类型安全性。与动态类型的语言相比&#xff0c;这可能会导致编译时间变长。Rust 的编译器在进行许多优化时需要大量…