memory动态内存管理学习之unique_ptr

news2024/10/5 17:19:11

此头文件是动态内存管理库的一部分。std::unique_ptr 是一种智能指针,它通过指针持有并管理另一对象,并在 unique_ptr 离开作用域时释放该对象。在发生下列两者之一时,用关联的删除器释放对象:

  • 管理它的 unique_ptr 对象被销毁。
  • 通过 operator= 或 reset() 赋值另一指针给管理它的 unique_ptr 对象。

成员函数

(构造函数)

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

(析构函数)

析构所管理的对象,如果存在的话
(公开成员函数)

operator=

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

release

返回一个指向被管理对象的指针,并释放所有权
(公开成员函数)

reset

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

swap

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

get

返回指向被管理对象的指针
(公开成员函数)

get_deleter

返回用于析构被管理对象的删除器
(公开成员函数)

operator bool

检查是否有关联的被管理对象
(公开成员函数)
单对象版本,unique_ptr<T>

operator*operator->

解引用指向被管理对象的指针
(公开成员函数)
数组版本,unique_ptr<T[]>

operator[]

提供到被管理数组的有索引访问
(公开成员函数)

代码示例:

#include <iostream>
#include <memory>

// unique_ptr deleter with state
class state_deleter {
	int count_;
public:
	state_deleter()
		:count_(0) {}
	template<class T>
	void operator()(T* p) {
		std::cout << "[deleted #" << ++count_ << "]\n";
		delete p;
	}
};

struct C{
	int a;
	int b;
};

int main()
{
	// unique_ptr constructor example
	std::default_delete<int> d;
	std::unique_ptr<int> u1;
	std::unique_ptr<int> u2(nullptr);
	std::unique_ptr<int> u3(new int);
	std::unique_ptr<int> u4(new int, d);
	std::unique_ptr<int> u5(new int, std::default_delete<int>());
	std::unique_ptr<int> u6(std::move(u5));
	std::unique_ptr<int> u7(std::move(u6));
	std::unique_ptr<int> u8(std::auto_ptr<int>(new int));

	std::cout << "u1: " << (u1 ? "not null" : "null") << '\n';
	std::cout << "u2: " << (u2 ? "not null" : "null") << '\n';
	std::cout << "u3: " << (u3 ? "not null" : "null") << '\n';
	std::cout << "u4: " << (u4 ? "not null" : "null") << '\n';
	std::cout << "u5: " << (u5 ? "not null" : "null") << '\n';
	std::cout << "u6: " << (u6 ? "not null" : "null") << '\n';
	std::cout << "u7: " << (u7 ? "not null" : "null") << '\n';
	std::cout << "u8: " << (u8 ? "not null" : "null") << '\n';

	// unique_ptr destructor example
	auto deleter = [](int *p) {
		delete p;
		std::cout << "deleter called\n";
	};
	std::unique_ptr<int, decltype(deleter)> foo(new int, deleter);
	std::cout << "foo " << (foo ? "is not" : "is") << " empty\n";

	// unique_ptr::operator= example
	std::unique_ptr<int> foo2;
	std::unique_ptr<int> bar2{ nullptr };
	foo2 = std::unique_ptr<int>(new int(101));  // rvalue
	bar2 = std::move(foo2);                       // using std::move

	std::cout << "foo2: ";
	if (foo2)
		std::cout << *foo2 << '\n';
	else
		std::cout << "empty\n";

	std::cout << "bar2: ";
	if (bar2)
		std::cout << *bar2 << '\n';
	else
		std::cout << "empty\n";

	// unique_ptr::get vs unique_ptr::release
											//foo3	bar3	p3
	std::unique_ptr<int> foo3;				//null
	std::unique_ptr<int> bar3;				//null	null
	int *p3 = nullptr;						//null	null	null
	std::cout << "foo3: ";
	if(foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if(bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if(p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	foo3 = std::unique_ptr<int>(new int(10));	//(10)	null	null
	bar3 = std::move(foo3);						//null  (10)	null
	p3 = bar3.get();							//null	(10)	(10)
	*p3 = 20;									//null	(20)	(20)
	p3 = nullptr;								//null	(20)	null
	std::cout << "foo3: ";
	if (foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if (bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if (p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	foo3 = std::unique_ptr<int>(new int(30));	//(30)	(20)	null
	p3 = foo3.release();						//null	(20)	(30)
	*p3 = 40;									//null	(20)	(40)
	std::cout << "foo3: ";
	if (foo3) std::cout << *foo3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "bar3: ";
	if (bar3) std::cout << *bar3 << '\n';
	else std::cout << "(null)\n";

	std::cout << "p3: ";
	if (p3) std::cout << *p3 << '\n';
	else std::cout << "(null)\n";
	std::cout << '\n';

	delete p3;   

	// unique_ptr::get_deleter example
	state_deleter del;
	std::unique_ptr<int> p; //使用默认的deleter;
	// alpha and beta use independent copies of the deleter:
	std::unique_ptr<int, state_deleter> alpha(new int);
	std::unique_ptr<int, state_deleter> beta(new int, alpha.get_deleter());
	// gamma and delta share the deleter "del" (deleter type is a reference!):
	std::unique_ptr<int, state_deleter&> gamma(new int, del);
	std::unique_ptr<int, state_deleter&> delta(new int, gamma.get_deleter());
	
	std::cout << "resetting alpha...";	alpha.reset(new int);
	std::cout << "resetting beta...";	beta.reset(new int);
	std::cout << "resetting gamma...";	gamma.reset(new int);
	std::cout << "resetting delta...";	delta.reset(new int);

	std::cout << "calling gamma/delta deleter...\n";
	gamma.get_deleter() = state_deleter();//新的deleter
	// additional deletions when unique_ptr objects reach out of scope (in inverse order of declaration)

	// example of unique_ptr::operator bool
	std::unique_ptr<int> foo4;
	std::unique_ptr<int> bar4(new int(12));
	if(foo4) std::cout << "foo4 points to " << *foo4 << '\n';
	else std::cout << "foo4 is empty\n";

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

	// unique_ptr::swap example
	std::unique_ptr<int> foo5(new int(10));
	std::unique_ptr<int> bar5(new int(20));
	std::cout << "foo5:" << *foo5 << '\n';
	std::cout << "bar5:" << *bar5 << '\n';
	foo5.swap(bar5);
	std::cout << "foo5:" << *foo5 << '\n';
	std::cout << "bar5:" << *bar5 << '\n';

	// unique_ptr::operator*
	std::unique_ptr<int> foo6(new int);
	std::unique_ptr<int> bar6(new int(100));
	std::cout << "foo6: " << *foo6 << '\n';
	std::cout << "bar6: " << *bar6 << '\n';
	*foo6 = *bar6 * 2;
	std::cout << "foo6: " << *foo6 << '\n';
	std::cout << "bar6: " << *bar6 << '\n';

	// unique_ptr::operator->
	std::unique_ptr<C> foo7(new C);
	std::unique_ptr<C> bar7;
	foo7->a = 10;
	foo7->b = 20;
	bar7 = std::move(foo7);
	if (foo7) std::cout << "foo7: " << foo7->a << ' ' << foo7->b << '\n';
	if (bar7) std::cout << "bar7: " << bar7->a << ' ' << bar7->b << '\n';

	// unique_ptr::operator[]
	std::unique_ptr<int[]> foo8(new int[5]);

	for (int i = 0; i < 5; ++i) 
		foo8[i] = i;

	for (int i = 0; i < 5; ++i)
		std::cout << foo8[i] << ' ';
	std::cout << '\n';

    return 0;
}


运行效果:

参考:

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

https://zh.cppreference.com/w/cpp/header/memory

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

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

相关文章

五款软件推荐:U盘数据不小心删除了?帮你快速找回!

U盘数据不小心删除了怎么恢复&#xff1f;U盘是一种便携式存储设备&#xff0c;因其小巧轻便而广受欢迎。但是&#xff0c;U盘也常常会遇到数据丢失的问题。当U盘数据丢失时&#xff0c;需要找到一款可靠的数据恢复软件来恢复数据。 接下来为大家推荐5款好用的免费U盘数据恢复软…

SmartDraw Suite Edition 画图软件画表格内存示意图的使用方法

总述&#xff1a;遇到不会画的&#xff0c;比如如何画一条虚线&#xff0c;先将 虚线 翻译成英文&#xff0c;然后在 help 中查询。 新建的时候选择如下&#xff1a; 一、选择 Forms->Blank Form 二、画表格&#xff1a; 三、画箭头&#xff1a;先选择1在选择2 四、编辑文…

基于睡眠声音评估睡眠质量

随着健康意识的增强&#xff0c;人们越来越关注睡眠质量。确保获得充足的高质量睡眠对于维持身体健康和心理平衡至关重要。专业的睡眠状态测量主要通过多导睡眠图&#xff08;PSG&#xff09;进行。然而&#xff0c;PSG会给受试者带来显著的身体负担&#xff0c;并且在没有专业…

力扣hot100学习记录(十二)

94. 二叉树的中序遍历 给定一个二叉树的根节点 root&#xff0c;返回它的中序遍历。 题意 给定一个二叉树&#xff0c;返回它的中序遍历 思路 采用递归的思想&#xff0c;只要根节点不为空&#xff0c;则一直递归遍历左子树&#xff0c;然后将根节点的值存入结果&#xff0c;…

深度学习中几种常见数据标准化方法

目录 一、介绍 二、总结 三、详情 1. StandardScaler 2. MinMaxScaler 3. RobustScaler 4. MaxAbsScaler 5. Normalizer 6. QuantileTransformer 7. PowerTransformer 8. Log Transform 四、示例 五、心得 一、介绍 方法名称缩放范围适用条件StandardScaler均值…

山水有相逢 来日皆可期

毕业接踵而至&#xff0c;大家都在拍照记录留恋毕业的美好时光碎片。但由于最近实在“玩得太嗨”&#xff0c;无心拍毕业照。 默海笑&#xff0c;当然是需要用自己的方式来为这浑浑噩噩的大学生活画上句号。 我相信&#xff0c;毕业时的你我都会无比的感慨&#xff0c;为什么时…

Matlab|遗传粒子群-混沌粒子群-基本粒子群

目录 1 主要内容 2 部分代码 3 效果图 4 下载链接 1 主要内容 很多同学在发文章时候最犯愁的就是创新点创新点创新点&#xff08;重要的事情说三遍&#xff09;&#xff0c;对于采用智能算法的模型&#xff0c;可以采用算法改进的方式来达到提高整个文章创新水平的目的&…

Autosar 通讯栈配置-手动配置PDU及Signal-基于ETAS软件

文章目录 前言System配置ISignalSystem SignalPduFrameISignal到System Signal的mapSystem Signal到Pdu的mapPdu到Frame的mapSignal配置Can配置CanHwFilterEcuC配置PduR配置CanIf配置CanIfInitCfgCanIfRxPduCfgCom配置ComIPduComISignalSWC配置Data mappingRTE接口Com配置补充总…

AXI Quad SPI IP核中的STARTUPEn原语参数

启动STARTUPEn Primitive &#xff08;原语&#xff09;参数在 FPGA的主 SPI模式下非常有用。当你启用这个参数时&#xff0c;对于 7 系列设备&#xff0c;STARTUPE2 原语会被包含在设计中&#xff1b;而对于 UltraScale™ 设备&#xff0c;则是 STARTUPE3 原语。这些原语在 FP…

时隔很久运行苍穹外卖项目,出现很多错误

中途运行了很多其他项目&#xff0c;maven的配置文件还被我修改了一次。导致再次运行苍穹外卖项目出现很多错误。 发现没有办法&#xff0c;把本地的仓库删了个干干净净。然后点击clean发现报错&#xff1a; Cannot access alimaven (http://mavejavascript:void(0);n.aliyun.…

线性代数|机器学习-P11方程Ax=b求解研究

文章目录 1. 变量数和约束条件数大小分类2. 最小二乘法和Gram-schmidt变换2.1 Gram-schmidt变换2.2 最小二乘法2.2.1 损失函数-Lasso 和regression2.2.2 损失函数-Lasso2.2.3 损失函数-regression2.2.4 Regression岭回归-矩阵验证2.2.5 Regression岭回归-导数验证 3. 迭代和随机…

牛客网刷题 | BC119 最高分与最低分之差

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 输入n个成绩&#…

STM32F103C8T6 HAL库串口重定向

前言&#xff1a; 这里仅用做个人记录&#xff0c;实现USART1串口通信&#xff0c;并通过printf重定向输出“串口打印测试” 正文开始&#xff1a; 首先在STM32CubeMX上对串口进行配置&#xff0c;其实方法也非常简单。 按照箭头顺序&#xff0c;先点击Connectivity找到USART1…

NineData云原生智能数据管理平台新功能发布|2024年5月版

重点发布​ 数据库 DevOps - 表分组查询​ 在企业用户规模达到一定程度后&#xff0c;分库分表成为一种常见的数据库架构选择。在这种情况下&#xff0c;查询和维护数据需要高效的解决方案&#xff0c;以避免手动逐一查询、变更和汇总多个分库和分表的繁琐操作。 库分组变更…

泛微开发修炼之旅--13通过Ecology拦截器(注解的方式),拦截后端接口,实现接口执行成功后或执行前操作源码示例

文章链接&#xff1a;泛微开发修炼之旅--13通过Ecology拦截器(注解的方式)&#xff0c;拦截后端接口&#xff0c;实现接口执行成功后或执行前操作源码示例

[个人感悟] Java基础问题应该考察哪些问题?

前言 “一切代码无非是数据结构和算法流程的结合体.” 忘了最初是在何处看见这句话了, 这句话, 对于Java基础的考察也是一样. 正如这句话所说, 我们对于基础的考察主要考察, 数据结构, 集合类型结构, 异常类型, 已经代码的调用和语法关键字. 其中数据结构和集合类型结构是重点…

牛客网刷题 | BC117 逆序输出

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 输入10个整数&…

ssm629基于SSM的二手交易平台设计与开发+jsp【已测试】

前言&#xff1a;&#x1f469;‍&#x1f4bb; 计算机行业的同仁们&#xff0c;大家好&#xff01;作为专注于Java领域多年的开发者&#xff0c;我非常理解实践案例的重要性。以下是一些我认为有助于提升你们技能的资源&#xff1a; &#x1f469;‍&#x1f4bb; SpringBoot…

安装windows11系统跳过微软账号登录,使用本地账号登录方法

在安装win11系统&#xff0c;进行到如图下所示界面的时候&#xff0c;暂停下 我们可以按下键盘的ShiftF10按键&#xff08;部分电脑是FnShiftF10&#xff09;&#xff0c;这时屏幕会出现命令行窗口&#xff0c;如图下所示 我们需要在命令行内输入代码oobe\bypassnro.cmd然后回车…

Linxu: Dynamic debug 简介

文章目录 1. 前言2. 什么是 Dynamic debug (dyndbg) ?3. Dynamic debug (dyndbg) 的使用3.1 开启 Dynamic debug (dyndbg) 功能3.2 使用 Dynamic debug (dyndbg) 功能 4. Dynamic debug (dyndbg) 的实现4.1 内核接口 dynamic_pr_debug() 的实现4.2 debugfs 导出控制节点 contr…