Learn C++学习笔记:第M章—最常用的智能指针:std::unique_ptr & std::make_unique_make_unique和unique_ptr-程序员宅基地

技术标签: C++  

1、基本使用介绍

前面已经介绍了很多智能指针了,它就是一个类。这么重要的类当然不需要我们手写,有现成的可以用,它就是:

std::unique_ptr

①、所在头文件

这是一个封装好的类,包含在头文件<memory>中。

②、初始化

初始的方式也跟正常的类使用一样:

std::unique_ptr<YourClass> res{
     new YourClass() };

③、智能指针之间的复制

std::unique_ptr是实现了移动语义的功能的并且禁用复制语义,在智能指针和智能指针之间的赋值时候,应该使用移动语义,先把智能指针通过std::move变成右值。

	std::unique_ptr<Resource> res1{
     new Resource{
    } }; // Resource created here
	std::unique_ptr<Resource> res2{
    }; // Start as nullptr
 
	res2 = std::move(res1);

④、重载* 、->

std :: unique_ptr具有重载的operator *operator->,可用于返回被管理的资源。Operator *返回对托管资源的引用,operator->返回指针。

template<class T>
class Auto_ptr3
{
    
	T* m_ptr;
 	.....省略....
	T& operator*() const {
     return *m_ptr; }
	T* operator->() const {
     return m_ptr; }
};

使用示例:

#include <iostream>
#include <memory> // for std::unique_ptr
 
class Resource
{
    
public:
	Resource() {
     std::cout << "Resource acquired\n"; }
	~Resource() {
     std::cout << "Resource destroyed\n"; }
	friend std::ostream& operator<<(std::ostream& out, const Resource& res)
	{
    
		out << "I am a resource\n";
		return out;
	}

	void test(){
     
		std::cout << "=======\n";
	}
};

int main()
{
    
	std::unique_ptr<Resource> res{
     new Resource{
    } };

	if (res) // use implicit cast to bool to ensure res contains a Resource
		std::cout << *res << '\n'; // print the Resource that res is owning
	res->test();
	return 0;
}

打印:

Resource acquired
I am a resource
=======
Resource destroyed

2、std :: make_unique

智能指针的初始化除了上面所示之外,更推荐使用std :: make_unique进行智能指针的创建。
使用std :: make_unique代码更简洁,并且可以避免一些错误。

auto f1{
     std::make_unique<Fraction>(3, 5) };

①直接使用auto当成类型关键字即可,std :: make_unique创建的类型就是std :: unique_ptr。
②std::make_unique<ClassName>(parameter……),中间填写类名称,后面的小括号里面跟上要初始化的类的参数。

3、std::unique_ptr传递给函数和函数返回

传递给函数,因为复制语义被禁用,所以显而易见,不能直接按值传递。
并且这里要分两种情况:
①函数里面可能会对智能指针内容进行更改:

#include <iostream>
#include <memory> // for std::unique_ptr
 
class Resource
{
    
public:
	Resource() {
     std::cout << "Resource acquired\n"; }
	~Resource() {
     std::cout << "Resource destroyed\n"; }
	friend std::ostream& operator<<(std::ostream& out, const Resource &res)
	{
    
		out << "I am a resource\n";
		return out;
	}
};
 
void takeOwnership(std::unique_ptr<Resource> res)
{
    
     if (res)
          std::cout << *res << '\n';
} // the Resource is destroyed here
 
int main()
{
    
    auto ptr{
     std::make_unique<Resource>() };
 
//    takeOwnership(ptr); // This doesn't work, need to use move semantics
    takeOwnership(std::move(ptr)); // ok: use move semantics
 
    std::cout << "Ending program\n";
    return 0;
}

但是需要注意的是,这里面的智能指针的销毁是在takeOwnership(std::move(ptr));后,而不是在main()后。

②如果不需要对指针内容更改,直接传递指针即可,通过get()函数,将智能指针里面的指针传递进去,使用完指针随着函数结束而销毁,并不会影响函数外面的智能指针。

#include <memory> // for std::unique_ptr
#include <iostream>
 
class Resource{
    
public:
	Resource() {
     std::cout << "Resource acquired\n"; }
	~Resource() {
     std::cout << "Resource destroyed\n"; }
 
	friend std::ostream& operator<<(std::ostream& out, const Resource &res)
	{
    
		out << "I am a resource\n";
		return out;
	}
};
 
// The function only uses the resource, so we'll accept a pointer to the resource, not a reference to the whole std::unique_ptr<Resource>
void useResource(Resource *res){
    
	if (res)
		std::cout << *res << '\n';
}
 
int main(){
    
	auto ptr{
     std::make_unique<Resource>() };
 
	useResource(ptr.get()); // note: get() used here to get a pointer to the Resource
 
	std::cout << "Ending program\n";
	return 0;
} // The Resource is destroyed here

③如果是函数返回智能指针,直接正常返回即可。

std::unique_ptr<Resource> createResource(){
    
     return std::make_unique<Resource>();
}
 
int main(){
    
    auto ptr{
     createResource() };
    // do whatever
    return 0;
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_39548859/article/details/114031936

智能推荐

c语言单元测试及答案,C语言程序设计单元测试答案-程序员宅基地

文章浏览阅读2k次。C语言程序设计 菏泽学院 黄复贤1【单选题】若定义pf为指向float类型变量f的指针,下列语句中__是正确的。A、float f, *pf = f;B、float f, *pf = &f;C、float *pf = &f, f;D、float f, *pf =0.0;正确答案:B2【单选题】若p1、p2都是整型指针,p1已经指向变量x,要使p2也指向x, ( )是正确的。A、p2..._若定义pf为指向float类型变量f的指针,下列语句中__是正确的。 a. float f, *pf =

《构建之法》第一次作业-程序员宅基地

文章浏览阅读134次。这个作业属于哪个课程这个作业要求在哪里我在这个课程的目标是理解软件开发流程,为以后的项目开发做好知识储备这个作业在哪个具体方面帮助我实现目标通过大量的阅读和查阅资料对专业有更深的认知,借鉴前辈们的经验之谈来更明确自己的想法我的博客地址icjy1.建立博客,介绍自己这是我的第一篇博客,而此时的我已经是一名软件工程专业的大三学生了。虽说读..._刘伊凡北航

华为鸿蒙能与车互联吗,华为鸿蒙上车,关于车联网的想象有多少?-程序员宅基地

文章浏览阅读6.1k次。尚未生在江湖,但江湖都是你的传说。这句话用来形容华为的鸿蒙 OS 再合适不过了。于是在众人瞩目中,华为鸿蒙系统终于揭开了面纱。8 月 9 日,华为消费者业务今天在其全球开发者大会上正式发布了基于微内核的面向全场景的分布式操作系统——鸿蒙 OS,其英文名 HarmonyOS,意为 " 和谐 ",华为消费者业务 CEO 余承东表示,是希望给世界带来更多和谐和方便," 未来的操作系统应当是微内核架构,可..._鸿蒙系统能车载安卓系统联网吗

OpenCV中的随机数与随机种子_opencv rand-程序员宅基地

文章浏览阅读1.8k次,点赞3次,收藏7次。我们先从在C/C++中的随机数与随机种子说起。rand()、srand()rand()可以生成一个0~RAND_MAX之间的一个随机数,返回值是一个unsigned int类型值。rand函数不是真正的随机数生成器,而srand()会设置供rand()使用的随机数种子。如果你在第一次调用rand()之前没有调用srand(),那么系统会为你自动调用srand()。而使用同种子相同的数调用..._opencv rand

三天刷完《剑指OFFER编程题》--Java版本实现(第二天)_剑指offer java版-程序员宅基地

文章浏览阅读1.1k次,点赞2次,收藏4次。正在更新中。。。。。。。。。剑指offer --Python版本的实现:剑指offer(1/3)第一大部分剑指offer(2/3)第二大部分剑指offer(3/3)第三大部分27.字符串的排列输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。输入描述:输入一个字符串,长度不超过9(可能有字符重复),字符只包括大小写字母。递归法,问题.._剑指offer java版

计算机视觉迎来GPT时刻!UC伯克利三巨头祭出首个纯CV大模型!-程序员宅基地

文章浏览阅读282次。点击下方卡片,关注“CVer”公众号AI/CV重磅干货,第一时间送达点击进入—>【视觉和Transformer】微信交流群扫码加入CVer知识星球,可以最快学习到最新顶会顶刊上的论文idea和CV从入门到精通资料,以及最前沿项目和应用!发论文,强烈推荐!在CVer微信公众号后台回复:LVM,即可下载论文pdf和代码链接!快学起来!转载自:机器之心仅靠视觉(像素)模型能走多远?UC 伯克利、约..._三巨头视觉大模型

随便推点

【Linux】定时任务调度-程序员宅基地

文章浏览阅读784次,点赞28次,收藏13次。1、接受在当天的hh:mm(小时:分钟)式的时间指定。假如该时间已过去,那么就放在第二天执行。例如:04:002、使用midnight(深夜),noon(中午),teatime(饮茶时间,一般是下午4点)等比较模糊的词语来指定时间。3、采用12小时计时制,即在时间后面加上AM(上午)或PM(下午)来说明是上午还是下午。例如:12pm4、指定命令执行的具体日期,指定格式为month day(月日)或mm/dd/yy(月/日/年)或dd.mm.yy(日.月.年),指定的日期必须跟在指定时间的后面。

nginx java文件上传_Nginx实现文件的上传和下载-程序员宅基地

文章浏览阅读2k次。文件的上传只要保证特殊的地址先到达Nginx,然后通过Nginx指定至指定的服务器即可,目前配置是本机。文件的下载的做法就是把本机的当前目录下面的文件给返回回去。server {listen ;server_name www.zj***.com zj***.com;#charset koi8-r;#access_log logs/host.access.log main;#资源上传,..._java 上传文件到nginx

Appfuse开发指南-程序员宅基地

文章浏览阅读2.7k次。这里是我写的一些文章内容提炼和链接,以方便大家能够找到一些有用的资料: Appfuse开发指南 如果你已经下载了AppFuse并且希望在你的机器上完成安装配置,最合适的参考资料是快速起步指南。一旦你完成了所有的安装设置,下面的手册是学习如何使用AppFuse开发的重要资料。 注意: Appfuse的发布包里面已经包括了这个指南。如果你希望更新你的工程目录下的手册(在 docs 目录下),运行 "a_appfuse

报名进入倒计时!让表格识别大赛承包您的硬核夏日(附保姆级参赛锦囊)_表计识别算法比赛-程序员宅基地

文章浏览阅读232次。截至9月8日 万元奖金+入职机会!好未来表格识别大赛自6月拉开序幕,来自全球各地的232+支队伍加入了这场技术派对,近300位社会各界的开发者们在云端切磋算法技艺,期待给这个夏天留下最硬核的记忆!目前赛程已过半,报名截至9月8日,盼君入席!只有真实的行业场景,才能考验开发者真正的实力!表格在教育场景中分布广泛,种类繁多。对表格结构的还原和内容的识别,能帮助计算机更好的理解表格,在教学内容生产、智能解答等场景下,具有非常重要的应用价值。本次大赛的赛题聚焦于教育场景下的表格识别技术,提供教育场景..._表计识别算法比赛

Ubuntu 应用之 截图工具-flameshot_ububtu用libreoffice截图-程序员宅基地

文章浏览阅读707次,点赞4次,收藏3次。Ubuntu 18自带有截图工具,但是使用方式以及使用功能都不是很理想。还好在GitHub上有flameshot这么一款强大的linux截图工具。下载地址:https://github.com/flameshot-org/flameshot直接下载“Download zip”安装方式:下载后打开终端,具体安装命令如下:sudo apt-get install flameshot启动后,长成这个样子,每一个紫色小圈圈都代表一个功能, 是不是很强大如果觉得每次启动不方._ububtu用libreoffice截图

解决“ ModuleNotFoundError: No module named ‘tensorflow.examples‘ “_modulenotfounderror: no module named 'tensorflow.e-程序员宅基地

文章浏览阅读1.2w次,点赞5次,收藏31次。这个问题是我在用tensorflow做mnist数据集案例,程序在pycharm 2019.3.1运行时出现的问题.原因是tensorflow中没有examples解决方法首先找到对应tensorflow的文件,我的是在D:\python3\Lib\site-packages\tensorflow(python的安装目录),进入tensorflow文件夹,发现没有examples文件夹。我们可以进入github下载:https://github.com/tensorflow/tensorflow_modulenotfounderror: no module named 'tensorflow.examples