memory动态内存管理学习之shared_ptr

此头文件是动态内存管理库的一部分。std::shared_ptr 是一种通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可持有同一对象。下列情况之一出现时销毁对象并解分配其内存:

  • 最后剩下的持有对象的 shared_ptr 被销毁;
  • 最后剩下的持有对象的 shared_ptr 被通过 operator= 或 reset() 赋值为另一指针。

成员函数

(构造函数)

构造新的 shared_ptr
(公开成员函数)

(析构函数)

如果没有更多 shared_ptr 指向所持有的对象,则析构该对象
(公开成员函数)

operator=

shared_ptr 赋值
(公开成员函数)
修改器

reset

替换所管理的对象
(公开成员函数)

swap

交换所管理的对象
(公开成员函数)
观察器

get

返回存储的指针
(公开成员函数)

operator*operator->

解引用存储的指针
(公开成员函数)

operator[]

(C++17)

提供到所存储数组的索引访问
(公开成员函数)

use_count

返回 shared_ptr 所指对象的引用计数
(公开成员函数)

unique

(C++20 前)

检查所管理对象是否仅由当前 shared_ptr 的对象管理
(公开成员函数)

operator bool

检查是否有关联的管理对象
(公开成员函数)

owner_before

提供基于持有者的共享指针排序
(公开成员函数)

示例代码

#include <iostream>
#include <memory>

struct C2 { int* data; };
struct C3 { int a; int b; };

int main()
{
	// shared_ptr constructor example
	std::shared_ptr<int> p1;
	std::shared_ptr<int> p2(nullptr);
	std::shared_ptr<int> p3(new int);
	std::shared_ptr<int> p4(new int, std::default_delete<int>());
	std::shared_ptr<int> p5(new int, [](int* p) {delete p; }, std::allocator<int>());
	std::shared_ptr<int> p6(p5);
	std::shared_ptr<int> p7(std::move(p6));
	std::shared_ptr<int> p8(std::unique_ptr<int>(new int));
	std::shared_ptr<C2> obj(new C2);
	std::shared_ptr<int> p9(obj, obj->data);

	std::cout << "use_count:\n";
	std::cout << "p1: " << p1.use_count() << '\t';
	std::cout << "p2: " << p2.use_count() << '\t';
	std::cout << "p3: " << p3.use_count() << '\t';
	std::cout << "p4: " << p4.use_count() << '\t';
	std::cout << "p5: " << p5.use_count() << '\n';
	std::cout << "p6: " << p6.use_count() << '\t';
	std::cout << "p7: " << p7.use_count() << '\t';
	std::cout << "p8: " << p8.use_count() << '\t';
	std::cout << "p9: " << p9.use_count() << '\n';

	// shared_ptr destructor example
	auto deleter = [](int *p) {
		std::cout << "[delete called]\n"; delete p;
	};
	std::shared_ptr<int> foo(new int, deleter);
	std::cout << "use_count:" << foo.use_count() << '\n';
	// shared_ptr::operator= example
	std::shared_ptr<int> foo2;
	std::shared_ptr<int> bar2(new int(10));
	foo2 = bar2;						//copy
	bar2 = std::make_shared<int>(20);	//move
	std::unique_ptr<int> unique(new int(30));
	foo2 = std::move(unique); //move from unique_ptr
	std::cout << "*foo2:" << *foo2 << '\t';
	std::cout << "*bar2:" << *bar2 << '\n';

	// shared_ptr::reset example
	std::shared_ptr<int> sp;	//empty
	sp.reset(new int);			//takes ownership of pointer
	*sp = 100;
	std::cout << *sp << '\n';
	sp.reset(new int);			//deletes managed object, acquires new pointer
	*sp = 200;
	std::cout << *sp << '\n';

	// shared_ptr::swap example
	std::shared_ptr<int> foo3(new int(101));
	std::shared_ptr<int> bar3(new int(201));
	foo3.swap(bar3);
	std::cout << "*foo3:" << *foo3 << '\t';
	std::cout << "*bar3:" << *bar3 << '\n';
	// shared_ptr::get example
	int *p = new int(10);
	std::shared_ptr<int> a(p);
	if(a.get() == p)
		std::cout << "a and p point to the same location\n";

	// three ways of accessing the same address:
	std::cout << *a.get() << "\t";
	std::cout << *a << "\t";
	std::cout << *p << "\n";
	// shared_ptr::operator*
	std::shared_ptr<int> foo4(new int);
	std::shared_ptr<int> bar4(new int(100));
	*foo4 = *bar4 * 2;
	std::cout << "foo4: " << *foo4 << '\t';
	std::cout << "bar4: " << *bar4 << '\n';
	// shared_ptr::operator->
	std::shared_ptr<C3> foo5;
	std::shared_ptr<C3> bar5(new C3);

	foo5 = bar5;

	foo5->a = 10;
	bar5->b = 20;

	if (foo5) std::cout << "foo5: " << foo5->a << ' ' << foo5->b << '\t';
	if (bar5) std::cout << "bar5: " << bar5->a << ' ' << bar5->b << '\n';
	// shared_ptr::unique
	std::shared_ptr<int> foo6;
	std::shared_ptr<int> bar6(new int);
	std::cout << "foo6 unique?\n" << std::boolalpha;
	std::cout << "1: " << foo6.unique() << '\t';  // false (empty)
	foo6 = bar6;
	std::cout << "2: " << foo6.unique() << '\t';  // false (shared with bar)
	bar6 = nullptr;
	std::cout << "3: " << foo6.unique() << '\n';  // true
	// example of shared_ptr::operator bool
	std::shared_ptr<int> foo7;
	std::shared_ptr<int> bar7(new int(34));
	if (foo7) std::cout << "foo7 points to " << *foo7 << '\n';
	else std::cout << "foo7 is null\n";

	if (bar7) std::cout << "bar7 points to " << *bar7 << '\n';
	else std::cout << "bar7 is null\n";

	// shared_ptr::owner_before
	int *p10 = new int(10);
	std::shared_ptr<int> a10(new int(20));
	std::shared_ptr<int> b10(a10, p10);  // alias constructor
	std::cout << "comparing a11 and b10...\n" << std::boolalpha;
	std::cout << "value-based: " << (!(a10 < b10) && !(b10 < a10)) << '\n';
	std::cout << "owner-based: " << (!a10.owner_before(b10) && !b10.owner_before(a10)) << '\n';

	delete p10;

    return 0;
}





运行效果:

参考:

https://cplusplus.com/reference/memory/shared_ptr/

std::shared_ptr - cppreference.com

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PID_Compact指令博图仿真

一、PID_Compact 指令管脚介绍 做仿真前&#xff0c;肯定要对主角有一定了解才能够按我们需要的去控制。 主要管脚介绍&#xff1a; 输入参数&#xff1a; setpoint&#xff1a;自动模式下的用户设定值&#xff1b; input&#xff1a;实际反馈值&#xff0c;非模拟量&#x…

[Linux] TCP协议介绍(2): TCP协议的“三次握手“过程分析、超时重传机制介绍...

上一篇文章中, 已经介绍了TCP协议的数据格式, 简单分析了其与UDP协议 关于可靠性方面的差异 本篇文章, 介绍分析一下 使用TCP协议通信, 非常重要的一个过程: 三次握手 TCP的"三次握手" TCP协议是有连接的传输层协议, 即使用TCP协议通信, 是需要建立连接的 TCP协议…

【LeetCode 动态规划】买卖股票的最佳时机问题合集

文章目录 1. 买卖股票的最佳时机含冷冻期 1. 买卖股票的最佳时机含冷冻期 题目链接&#x1f517; &#x1f34e;题目思路&#xff1a; &#x1f34e;题目代码&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {int n prices.size();ve…

快手爬票概述

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 无论是出差还是旅行&#xff0c;都无法离开交通工具的支持。现如今随着科技水平的提高&#xff0c;高铁与动车成为人们喜爱的交通工具。如果想要知道…

代码随想录二刷DAY1~3

Day1 704 二分查找&#xff0c;简单 我也有自己写题解的能力了&#xff0c;而且思维很清晰&#xff1a; 找什么就在if里写什么。 class Solution {public: int search(vector<int>& nums, int target) { int l0,rnums.size()-1; while(l<r){ …

【计算机网络】已解决:“‘ping‘ 不是内部或外部命令,也不是可运行的程序或批处理文件”报错

文章目录 一、问题分析背景二、可能出错的原因三、错误代码示例四、正确解决方法与示例五、注意事项 已解决“‘ping’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件”报错 一、问题分析背景 在Windows操作系统中&#xff0c;ping 命令是一个常用的网络诊断…

动态规划的递归写法和递推写法详解

目录 动态规划的概念 动态规划的递归写法 动态规划的递推写法 动态规划的概念 动态规划是一种用来解决一类最优化问题的算法思想。简单来说&#xff0c;动态规划将一个复杂的问题分解成若干个子问题&#xff0c;通过综合子问题的最优解来得到原问题的最优解。需要注意的是&…

【stm32-新建工程】

stm32-新建工程 ■ 下载相关STM32Cube官方固件包&#xff08;F1&#xff0c;F4&#xff0c;F7&#xff0c;H7&#xff09;■ 1. ST官方搜索STM32Cube■ 2. 搜索 STM32Cube■ 3. 点击获取软件■ 4. 选择对应的版本下载■ 5. 输入账号信息■ 6. 出现下载弹框&#xff0c;等待下载…

Codeforces Round 953 (Div. 2)(A~D题解)

这次比赛是我最顺利的一次比赛&#xff0c;也是成功在中途打进前1500&#xff0c;写完第三道题的时候也是保持在1600左右&#xff0c;但是后面就啥都不会了&#xff0c;还吃了点罚时&#xff0c;虽说如此也算是看到进步了&#xff0c;D题学长说很简单&#xff0c;但是我当时分析…

如何实现“变”CF而不变有效值

存在一些特殊需求,需要在保证有效值不变的情况下,“改变”正弦波的峰值因数(CF),如图,由绿色波形变为灰色波形: 正常的正弦波为 f ( t ) = 2 A ⋅ s i n ( 2 π T t ) f(t)=\sqrt{2}A\cdot sin(\frac{2\pi}{T}t) f(t)=2 ​A⋅sin(T2π​t) ,CF值为 2 \sqrt{2} 2 ​ …

Vue路由守卫的使用

示例如下&#xff1a;&#xff08;第一张图&#xff09;当你点击车1的时候你写了路由守卫就点不开出现无权访问 &#xff08;第二张图&#xff0c;就是可以访问后的图&#xff09;有路由守卫点不开的情况下当你在本地存储中写了你在路由守卫中写的东西就可以进入了 你需要在r…

[文献解读]:斯坦福最新研究-HumanPlus:人形机器人跟踪和模仿人类

摘要 制造具有与人类相似外形的机器人的关键论点之一是&#xff0c;我们可以利用大量人类数据进行训练。然而&#xff0c;由于人形机器人感知和控制的复杂性、人形机器人与人类在形态和驱动方面仍然存在的物理差距&#xff0c;以及人形机器人缺乏从自我中心视觉学习自主技能的…

基于STM32和人工智能的自动驾驶小车系统

目录 引言环境准备自动驾驶小车系统基础代码实现&#xff1a;实现自动驾驶小车系统 4.1 数据采集模块4.2 数据处理与分析4.3 控制系统4.4 用户界面与数据可视化应用场景&#xff1a;自动驾驶应用与优化问题解决方案与优化收尾与总结 1. 引言 随着人工智能和嵌入式系统技术的…

Oracle--存储结构

总览 一、逻辑存储结构 二、物理存储结构 1.数据文件 2.控制文件 3.日志文件 4.服务器参数文件 5.密码文件 总览 一、逻辑存储结构 数据块是Oracle逻辑存储结构中的最小的逻辑单位&#xff0c;一个数据库块对应一个或者多个物理块&#xff0c;大小由参数DB_BLOCK_SIZE决…

一段代码读取Chrome存储的所有账号密码和Cookie

先写结论&#xff1a; Chrome密码管理里的账号密码&#xff0c;还有Cookie&#xff0c;安全性并不算太高&#xff0c;一段代码就可以自动读取并上报到其它地方。 尤其是国内用户大多喜欢破解软件&#xff0c;这些软件只要注入这样一段代码&#xff0c;就无声无息的把你的所有账…

KT-H6测距模块标品,测距范围1500m,demo报价1000RMB,批量报价500RMB

激光测距传感器是一种用于测量距离的模块,通常由传感器和相关电子设备组成,测距模块可以集成到各种设备和系统中,以实现准确的测距和定位功能。KT-H6系列激光测距模块,为自主研发,激光波长905nm的激光器,专为热成像、夜视仪、无人机、安防、瞄具等产品定身打造,其优点是…

算法与数据结构--决策树算法

欢迎来到 Papicatch的博客 文章目录 &#x1f349;决策树算法介绍 &#x1f348;原理 &#x1f348;核心思想包括 &#x1f34d;递归分割 &#x1f34d;选择标准 &#x1f34d;剪枝 &#x1f348;解题过程 &#x1f34d;数据准备 &#x1f34d;选择最佳分割特征 &…

分类模型部署-ONNX

分类模型部署-ONNX 0 引入&#xff1a;1 模型部署实战测试&#xff1a;1 安装配置环境&#xff1a;2 Pytorch图像分类模型转ONNX-ImageNet1000类3 推理引擎ONNX Runtime部署-预测单张图像&#xff1a; 2 扩展阅读参考 0 引入&#xff1a; 在软件工程中&#xff0c;部署指把开发…

消息队列-RabbitMQ-延时队列实现

死信队列 DLX,全称为Dead-Letter-Exchange,死信交换机&#xff0c;死信邮箱。当消息在一个队列中变成死信之后&#xff0c;它能重新发送到另外一个交换器中&#xff0c;这个交换器就是DLX&#xff0c;绑定DLX的队列就称为死信队列。 导致死信的几种原因&#xff1a; ● 消息…

Swift开发——简单函数实例

函数是模块化编程的基本单位,将一组完成特定功能的代码“独立”地组成一个执行单位,称为函数。函数的基本结构如下所示: 其中,func为定义函数的关键字;“函数名”是调用函数的入口;每个函数可以有多个参数,即可以有多个“参数标签 参数名称:参数类型”,一般地,各个参…