【C++11及其特性】智能指针——unique_ptr

news2024/11/15 17:17:38

unique_ptr目录

  • 一.排他所有权模式
  • 二.auto_ptr的缺点
    • 1.可以直接复制和拷贝构造
    • 2.STL可以直接赋值
    • 3.不支持动态内存分配数组
  • 三.unique_ptr(C++11)
    • 1.不支持直接赋值和构造
    • 2.STL可以不可以直接赋值
    • 3.支持动态内存分配数组
  • 四.unique_ptr的用法
    • 1.构造函数
    • 2.赋值操作
    • 3.主动释放对象
    • 4.放弃对象控制权
    • 5.重置
    • 6.交换
  • 五.排他性智能指针的陷阱
  • 六.完整代码
  • 七.总结

一.排他所有权模式

在这里插入图片描述
运行结果:
在这里插入图片描述
auto_ptr和unique_ptr都是排他所有权模式,就是一块内存只能一个指针来管理.

所以这个过程是p1先释放,然后被p2赋值,p2就释放了.

二.auto_ptr的缺点

1.可以直接复制和拷贝构造

在这里插入图片描述
这里就是可以直接赋值,但是其真正的跟我们的赋值又存在着差异.
不符合习惯.赋值后p2是空的.

2.STL可以直接赋值

在这里插入图片描述
在这里插入图片描述

原理和刚刚的赋值其实是一样的

3.不支持动态内存分配数组

auto_ptr只支持单个的动态内存分配.
在这里插入图片描述

三.unique_ptr(C++11)

1.不支持直接赋值和构造

unique_ptr则不允许直接赋值和构造,因为排他性.
这样也符合我们的习惯.
在这里插入图片描述
如果硬要转的话,可以用move移动语义,将左值变为右值.
在这里插入图片描述

2.STL可以不可以直接赋值

在这里插入图片描述

3.支持动态内存分配数组

在这里插入图片描述

四.unique_ptr的用法

以下将会用Test类来测试.
在这里插入图片描述

1.构造函数

  • 没有指向值的.
    在这里插入图片描述
  • 直接初始化的.
    在这里插入图片描述
  • 数组的.
    在这里插入图片描述
  • 带删除器的,就是生命周期结束的话,调用的自定义的,可能要在释放前做点什么.
    在这里插入图片描述
    在这里插入图片描述
    运行结果:
    在这里插入图片描述

2.赋值操作

  • 通过reset()赋值
    在这里插入图片描述
  • 通过move语义赋值
    在这里插入图片描述

3.主动释放对象

不用等生命周期结束.
在这里插入图片描述

4.放弃对象控制权

不管理其释放了.
在这里插入图片描述

5.重置

重置指向的指针.
在这里插入图片描述

6.交换

交换指向的指针.
在这里插入图片描述

五.排他性智能指针的陷阱

排他所有权模式,虽然让我们无法两个指针指向同一块内存.
但是当使用reset时,可以使其两个指针指向同一块内存了.
如果一个生命周期结束,那么下一个生命周期结束的话又会进行释放,导致重复释放.
在这里插入图片描述

六.完整代码

#include <iostream>
#include <memory>
#include <vector>
using namespace std;

int main1()
{
	auto_ptr<string>p1(new string("我是p1"));
	auto_ptr<string>p2(new string("我是p2"));
	cout << *p1 << endl;
	cout << *p2 << endl;
	cout << p1.get() << endl;
	cout << p2.get() << endl;
	p1 = p2;//排他所有权模式
	cout << *p1 << endl;
	//cout << *p2 << endl;//为空,不能访问
	cout << p1.get() << endl;
	cout << p2.get() << endl;
	cout << endl;

	vector<auto_ptr<string>>va;
	auto_ptr<string>p3(new string("我是p3"));
	auto_ptr<string>p4(new string("我是p4"));
	va.push_back(move(p3));
	va.push_back(move(p4));
	cout << va[0].get() << endl;
	cout << va[1].get() << endl;
	va[0] = va[1];
	cout << va[0].get() << endl;
	cout << va[1].get() << endl;
	cout << *va[0] << endl;
	//cout << *va[1] << endl;//不能访问为空

	//auto_ptr<int []>ai(new int[5]);

	//陷阱
	auto_ptr<string>p5;
	auto_ptr<string>p6;
	string* str = new string("智能指针的内存管理陷阱");
	p5.reset(str);
	{
		p6.reset(str);
	}
	cout << p6.get() << endl;
	cout << p5.get() << endl;
	system("pause");

	return 0;
}


int main2()
{
	unique_ptr<string>p1(new string("我是p1"));
	unique_ptr<string>p2(new string("我是p2"));
	cout << *p1 << endl;
	cout << *p2 << endl;
	cout << p1.get() << endl;
	cout << p2.get() << endl;
	//p1 = p2;//直接报错不允许
	//unique_ptr<string>p7(p1);//拷贝构造也不可以

	unique_ptr<string>p7(move(p1));
	p1 = move(p2);//只有只有才可以赋值

	cout << *p1 << endl;
	//cout << *p2 << endl;
	cout << p1.get() << endl;
	cout << p2.get() << endl;
	cout << endl;

	vector<unique_ptr<string>>va;
	unique_ptr<string>p3(new string("我是p3"));
	unique_ptr<string>p4(new string("我是p4"));
	va.push_back(move(p3));
	va.push_back(move(p4));
	cout << va[0].get() << endl;
	cout << va[1].get() << endl;
	//va[0] = va[1];//不允许赋值
	cout << va[0].get() << endl;
	cout << va[1].get() << endl;
	cout << *va[0] << endl;
	//cout << *va[1] << endl;

	//auto_ptr<int []>ai(new int[5]);
	unique_ptr<int[]>ui(new int[5]);//支持

	//陷阱
	auto_ptr<string>p5;
	auto_ptr<string>p6;
	string* str = new string("智能指针的内存管理陷阱");
	p5.reset(str);
	{
		p6.reset(str);
	}
	cout << p6.get() << endl;
	cout << p5.get() << endl;
	system("pause");

	return 0;
}

class Test
{
public:
	Test()
	{
		cout << "调用构造函数" << endl;
	}
	~Test()
	{
		cout << "调用析构函数" << endl;
	}

	void doSomething()
	{
		cout << "do...." << endl;
	}
};

class DestrucTest
{
public:
	void operator()(Test* p)
	{
		p->doSomething();
		delete p;
	}
};

int main()
{
	//赋值
	unique_ptr<Test>up1;
	Test* t = new Test();
	up1.reset(t);
	unique_ptr<Test>up2(new Test());
	unique_ptr<Test>up3;
	up3 = move(up2);
	up3.release();

	unique_ptr<Test[]>up4(new Test[5]);
	up4 = NULL;//主动释放,up4.reset()也可以
	

	{
		unique_ptr<Test, DestrucTest>up5(new Test());
	}

	unique_ptr<Test>up6(new Test());
	unique_ptr<Test>up7(new Test());
	up6.swap(up7);


	system("pause");
	return 0;
}

七.总结

用排他性的智能指针时,就用独一无二的unique_ptr.
auto_ptr已经被淘汰了!

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

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

相关文章

免费的电脑录屏软件,这几款软件满足录屏需求!

在数字化时代&#xff0c;电脑录屏已成为我们日常生活和工作中不可或缺的一部分。无论是教学演示、游戏直播、会议记录&#xff0c;还是视频创作&#xff0c;一款优秀的录屏软件都是不可或缺的。今天&#xff0c;就为大家推荐几款免费、高效、易用的电脑录屏软件&#xff0c;帮…

首批国自然博士项目获批名单

【SciencePub学术】从公开新闻来看&#xff0c;已经有20所高校的博士生获批项目&#xff0c;分别是北京大学、清华大学、北京航空航天大学、东南大学、复旦大学、华中科技大学、吉林大学、兰州大学、南方科技大学、南开大学、山东大学、上海交通大学、四川大学、武汉大学、南京…

VSCode必备插件!快看过来!

同学同学&#xff0c;你是不是也很头疼VSCode不知道安装什么插件啊&#xff1f;尤其是萌新小白&#xff0c;更是一头雾水&#xff0c;那就快来一起看看吧~我帮你整理了一些非常实用的插件&#xff0c;安装上它们&#xff0c;你的开发体验会大大提升&#xff01; 1. Chinese (S…

DWG如何转换成PDF?总结了四种转换

DWG如何转换成PDF&#xff1f;在日常工作和学习中&#xff0c;经常需要将CAD软件中的DWG文件转换为PDF格式&#xff0c;以便于更广泛地分享和查阅。那么具体要怎么做&#xff0c;才能实现两种格式的顺利转换呢&#xff1f;为了帮助读者轻松完成这一任务&#xff0c;本文将详细介…

网络价格管控行动:四大策略,打击低价

网络价格管控的举措 设定最低售价约束&#xff1a;品牌方能够与在线零售商订立协议&#xff0c;清晰界定产品的最低售价&#xff0c;以守护品牌形象与市场秩序。推行动态定价策略&#xff1a;依照市场需求、竞争态势以及库存状况动态调节产品价格&#xff0c;保障市场竞争力并…

Java爬虫开发:Jsoup库在图片URL提取中的实战应用

在当今的互联网时代&#xff0c;数据的获取和处理变得尤为重要。对于网站内容的自动化抓取&#xff0c;爬虫技术扮演着不可或缺的角色。Java作为一种广泛使用的编程语言&#xff0c;拥有丰富的库支持网络爬虫的开发。其中&#xff0c;Jsoup库以其简洁、高效的特点&#xff0c;成…

51单片机 - 定时器0(按键控制LED流水灯模式)

时间&#xff1a;2024.9.2 目的&#xff1a;手撕51 作者&#xff1a;Whappy 定时器0寄存器配置 1.定时器0配置过程 首先要配置定时器的寄存器TCON和TMOD使计数器开始计数及定时器的初始值&#xff0c;配置使这个链路连起来。 #include <REGX52.H>void Timer0_Init() {…

【HarmonyOS 4.0】鸿蒙应用模型

应用模型是HarmonyOS为开发者提供的应用程序所需能力的抽象提炼&#xff0c;它提供了应用程序必备的组件和运行机制。有了应用模型&#xff0c;开发者可以基于一套统一的模型进行应用开发&#xff0c;使应用开发更简单、高效。随着系统的演进发展&#xff0c;HarmonyOS先后提供…

java 实现文本转音频

文章目录 一、前言二、实现流程2.1 下载jacob-1.18.zip2.2 拷贝jacob-1.18-x64.dll2.3 pom 添加依赖2.4 代码实现 一、前言 本文基于Windows自带的SAPI.SpVoice&#xff0c;通过java代码实现文本转语音的功能。 二、实现流程 2.1 下载jacob-1.18.zip 链接&#xff1a;https…

红帽认证初级有用吗?对个人帮助,报名时间分享

红帽认证初级即红帽认证系统管理员&#xff08;RHCSA&#xff09;是有用的。 拥有 RHCSA 认证的管理员掌握了 Linux 操作系统的基本知识和技能&#xff0c;能够准确理解和解决系统操作中的各种问题。他们了解并熟悉 Linux 命令行和 GUI 界面&#xff0c;可以高效地完成各种任务…

OpenCV绘图函数(15)图像上绘制矩形函数 rectangle()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 绘制一个简单的、粗的或填充的直立矩形。 这个函数 cv::rectangle 绘制一个矩形轮廓或一个填充的矩形&#xff0c;其两个相对的顶点分别是 pt1 和…

大数据-114 Flink DataStreamAPI 程序输入源 自定义输入源 Rich并行源 RichParallelSourceFunction

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

(五)vForm 动态表单文件上传、下载

系列文章目录 (一)vForm 动态表单设计器之使用 (二)vForm 动态表单设计器之下拉、选择 (三)vForm 动态表单解决下拉框无数据显示id问题 (四)vForm 动态表单自定义组件、属性 目录 系列文章目录 前言 一、文件上传 1.前端 2.后端 二、文件下载 1.前端 2.后端 总结 …

你可能被 Vue 中的 v-show 骗了,它并没有像你想的那样切换 display 的属性

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注&#xff01; 在 Vue 中 v-show 是如何条件性地渲染内容的&#xff0c;你可能知道是通过切换 display 属性实现&#xff0c;但真的跟你想的一样吗&#xff1f; 一、你被骗了吗&#xff1f; v-show 和 v-…

JAVAEE初阶第三节——多线程进阶

系列文章目录 JAVAEE初阶第三节——多线程进阶 文章目录 系列文章目录JAVAEE初阶第三节——多线程进阶 一. 常见的锁策略1.乐观锁和悲观锁2. 轻量级锁和重量级锁3.自旋锁和挂起等待锁4. 普通互斥锁和读写锁5. 公平锁和非公平锁6.可重入锁和不可重入锁 二. synchronized的优化手…

GEE数据集:城市热岛强度 (UHII)

简介 城市热岛强度 (UHII) 数据集说明 城市热岛效应&#xff08;UHI&#xff09;的特点是城市地区局部变暖&#xff0c;是城市化对气候造成的一个重要后果。 传统的估算 UHI 强度&#xff08;UHII&#xff09;的方法受到一些限制&#xff0c;例如只关注晴空表面 UHII&#x…

windows11 任务栏 默认打开显示所有其他系统托盘图标

任务栏所有图标显示&#xff1a; ①&#xff0c;WINR键 ②&#xff0c;输入&#xff1a;shell:::{05d7b0f4-2121-4eff-bf6b-ed3f69b894d9} ③&#xff0c;设置&#xff1a;始终在任务栏显示所有图标和通知

【负载均衡】

一、生产者负载均衡 可解决以下问题 消息发送的容灾策略:您可以根据生产者负载均衡策略,明确当局部节点出现故障时,消息发送如何进行容灾切换。 消息发送的顺序性机制:通过生产者负载均衡策略,您可以进一步了解顺序消息发送时,如何保证相同消息组内消息的先后顺序。 消息…

《JavaEE进阶》----8.<SpringMVC实践项目:【简易对话留言板(数据存在内存中)】>

本篇博客讲解设计的一个网页版简易对话留言板。这个是将数据存在内存中。 创建了一个集合 List<MessageInfo> messageInfos new ArrayList<>(); 在这里面存入的数据。当服务器重新加载的时候&#xff0c;数据就消失了&#xff0c;下一个版本&#xff0c;是将数据存…

StateThreads 库使用

文章目录 需求介绍协程注意调度 部署环境搭建测试测试库是否正常测试TCP服务器 需求 最近在对网关模型的并发性能进行验证&#xff0c; 核心目标不仅是让服务器能够承载更多的请求&#xff0c; 还力求在协议栈的解析阶段实现极致的轻量化和无锁操作&#xff0c;从而大幅提升处理…