Th5.6:智能指针(unique_ptr)之详述1

2023-11-03

本小节学习的知识点分别是智能指针(unique_ptr)之详述、常用操作。

今天总结的知识分为以下2个大点:

(1)unique_ptr概述、常用操作
    (1.1)常规初始化(unique_ptr和new配合)
    (1.2)make_unique()函数
(2)unique_ptr的常用操作
    (2.1)unique_ptr不支持的操作
    (2.2)移动语义
    (2.3)release()
    (2.4)reset()
    (2.5)=nullptr
    (2.6)指向一个数组
    (2.7)get()
    (2.8)*解引用
    (2.9)swap()
    (2.10)智能指针的名字作为判断条件
    (2.11)转换为sahred_ptr类型

(1)unique_ptr概述、常用操作:

        unique_ptr:独占式(专属)的指针。(所谓独占式,也即同一时刻,是一个unique_ptr智能指针只能指向对应的一个对象(这块内存))当该unique_ptr指针被销毁时,其所指向的内存就会给释放掉。(Boost库中的scoped_ptrunique_ptr类似!它也是独占式的智能指针)
    (1.1)常规初始化(unique_ptr和new配合):

unique_ptr<int> unptr1;
//unptr1是指向一个int型对象的空指针
unique_ptr<int> unptr2(new int(12));
//unptr2是指向一个int型对象val为12的unique_ptr智能指针

   (1.2)make_unique()函数(推荐使用):

        make_unique()函数是C++14中才引入的,C++11时还没引入这么个函数。当然,和shared_ptr的make_shared()函数一样,它们都不支持指定删除器的功能!若你想自定义删除器deleter的话,就不能使用make_unique()函数啦!

unique_ptr<double> unptr3 = make_unique<double>(1.88);
//unptr2是指向一个double型对象val为1.88的unique_ptr智能指针
auto unptr4 = make_unique<float>(1.98f);
//unptr4是指向一个float型对象val为1.98f的unique_ptr智能指针

(2)unique_ptr的常用操作:

        (2.1)unique_ptr不支持的操作:

        unique_ptr智能指针不支持拷贝以及赋值给别的指针这样的操作!

unique_ptr<string> ptr1 = make_unique<string>("I Love China!");
//unique_ptr<string> ptr2(ptr1);//❌!
//unique_ptr<string> ptr3 = ptr1;//❌!
//unique_ptr<string> ptr4;//❌!
//ptr4 = ptr1;//❌!
//这些代码都是错误的!因为unique_ptr这个指针不支持这些拷贝和赋值给别的指针的操作!

        (2.2)移动语义:

        用std::move()函数将一个unique_ptr指针所指向内存的控制权限移动(交给)给另一个unique_ptr指针,此时原来的unique_ptr指针就置为nullptr(且根据使用move函数的规则,你一旦移动完之后,就不能再对原来的指针do事情了!)

unique_ptr<string> ptr1 = make_unique<string>("I Love China!");
unique_ptr<string> ptr2(std::move(ptr1));
//cout << "*ptr1" << *ptr1 << endl;//构造函数将ptr1的内存控制权限移动给(交给)了ptr2
cout << "*ptr2 = " << *ptr2 << endl;

运行调试结果:

        在执行unique_ptr<string> ptr2(std::move(ptr1));这行代码之前的调试结果:

         在执行unique_ptr<string> ptr2(std::move(ptr1));这行代码之后的调试结果:

     (2.3).release():

        .release()方法的作用:放弃对该unique_ptr指针所指向对象的资源管理权。人话:将该unique_ptr指针置为nullptr的同时,返回其所指向的这个裸指针。当然,一旦你要用.release()方法这么do时,必须手动释放该裸指针所指向的内存!

一般对unique_ptr指针使用.release()方法时都要写如下三行codes

delete语句以及用一个对应类型的指针变量来接住指针所指向的裸指针语句这2行代码是缺一不可的

unique_ptr<double> unptr1 = make_unique<double>(8.88);
auto  ptr = unptr1.release();
delete ptr;//释放内存!若你不释放的话,unique_ptr这个类模板内部给你new的指针你就没释放
//这就会造成内存泄露leakage!

调试运行结果:

再比如:

unique_ptr<double> unptr1 = make_unique<double>(8.88);
unique_ptr<double> unptr2(unptr1.release());
//将unptr1所指向的double*的裸指针绑定到unptr2这个unique_ptr智能指针上!
unptr2.release();//直接release掉但是并没有手动释放unptr2所指向的double*裸指针的话
//就会造成内存泄露leakage!

运行调试结果:

        在unique_ptr<double> unptr2(unptr1.release());这行代码执行前的调试运行结果:

        在unique_ptr<double> unptr2(unptr1.release());这行代码执行后调试运行结果:

     (2.4).reset():

        a).reset(不带参数)方法的作用:释放 unique_ptr指针所指向的对象,并将该指针置为nullptr(空)。

unique_ptr<int> unptr = make_unique<int>(89);
unptr.reset();//将unptr置为nullptr并释放其原来所指向对象的内存!
if (unptr == nullptr)cout << "unptr == 空!" << endl;

        b).reset(新的指针对象)方法的功能:释放unique_ptr指针所指向的原对象,并将该指针置为新的指针对象。

unique_ptr<int> unptr = make_unique<int>(89);
unptr.reset(new int(888));//将unptr置为int型的对象888并释放其原来所指向对象的内存!
cout << *unptr << endl;//result = 888
	//or
unique_ptr<int> unptr1 = make_unique<int>(11);
unique_ptr<int> unptr2 = make_unique<int>(22);
unptr2.reset(unptr1.release());//将unptr置为unptr1指向的对象,并释放unptr2原所指向对象的内存!
cout << *unptr2 << endl;//result = 11

    (2.5)=nullptr:

        =nullptr方法的作用:将该unique_ptr指针置为nullptr空,并释放其所指向的对象。

unique_ptr<int> uniptr(new int(188));
uniptr = nullptr;//此时会释放uniptr所指向的对象,并且uniptr置空nullptr

    (2.6)指向一个数组:

        当unique_ptr智能指针指向一个数组对象时,<内就要加上elemTypeName[]>

unique_ptr<int[]> parr(new int[2]);
//注意:当unique_ptr智能指针指向一个数组时,<内就要加上elemType[]>
parr[0] = 1;
parr[1] = 12;
cout << parr[0] << endl;//result: 1
cout << parr[1] << endl;//result: 12

unique_ptr<A[]> parr2(new A[2]);
//这个unique_ptr智能指针指向一个A类型的且只有2个元素的数组

    (2.7).get():

        .get()方法的作用:返回unique_ptr智能指针所保存的裸指针。(正因为有些第三方库函数需要用到内置的裸指针,所以就引入该函数)

        注意①:用来.get()方法后,务必要记得不要释放该裸指针(delete p)所指向的内存,因为你这么干那你为啥还需要用unique_ptr这个智能指针来帮你管理内存呢?对吧?

        注意②:务必要记得不要将该裸指针所指向的内存绑定到另一个unique_ptr指针身上,因为你这么干会造成重复释放同一内存空间的异常问题。

unique_ptr<string> ptr1(new string("I Love China!"));
//*ptr1 = "I Love China!"
string * tp = ptr1.get();
*tp = "I Love you!";
//*tp = "I Love you!"

    (2.8)*解引用:

        与普通指针一样,智能指针也可以用*号do解引用,作用:获取该指针所指向的对象!

unique_ptr<string> ptr1(new string("I Love China!"));
cout << "*ptr1 = "<< * ptr1 << endl;
//*ptr1 = "I Love China!"
unique_ptr<string> ptr2(new string("You Love China!"));
cout << "*ptr2 = " << *ptr2 << endl;
//*ptr1 = "You Love China!"

unique_ptr<int[]> pp(new int[11]);
//对于数组,可直接用指针名+[index]来访问对应的elem
pp[0] = 0;
pp[1] = 1;

    (2.9)swap():

        .swap()方法的作用:用于交换2个unique_ptr智能指针所指向的对象!

unique_ptr<string> ps1(new string("lzf1"));
unique_ptr<string> ps2(new string("lzf2"));
cout <<"std::swap前:*ps1 = " <<*ps1 << " *ps2 = " << *ps2 << endl;
std::swap(ps1, ps2);
cout << "std::swap后:*ps1 = " << *ps1 << " *ps2 = " << *ps2 << endl;
ps1.swap(ps2);
cout << ".swap后:*ps1 = " << *ps1 << " *ps2 = " << *ps2 << endl;

运行结果:

     (2.10)智能指针的名字作为判断条件:

        用unique_ptr智能指针的名字作为if语句的判断条件。

unique_ptr<int> ptr(new int(1));
if (ptr)cout << "ptr非空!" << endl;
else cout << "ptr为空!" << endl;
ptr.reset();
if (ptr)cout << "ptr非空!" << endl;
else cout << "ptr为空!" << endl;


    (2.11)转换为shared_ptr类型:

        因为shared_ptr指针类模板中,含有显式构造函数,这个构造函数可用于将右值的unique_ptr指针转换为shared_ptr指针!

显式构造函数的源码:

explicit shared_ptr(_Ux* _Px) { // construct shared_ptr object that owns _Px
    if constexpr (is_array_v<_Ty>) {
        _Setpd(_Px, default_delete<_Ux[]>{});
    }else {
        _Temporary_owner<_Ux> _Owner(_Px);
        _Set_ptr_rep_and_enable_shared(_Owner._Ptr, new _Ref_count<_Ux>(_Owner._Ptr));
        _Owner._Ptr = nullptr;
    }
}

例子1:

unique_ptr<string> puns(new string("I Love China!"));
//puns是一个左值!
shared_ptr<string> ps1 = puns;//❌错误!
shared_ptr<string> ps2 = std::move(puns);//√!

例子2:

auto myfunc() {
	return unique_ptr<string>(new string("I Love China!"));
	//这是一个右值,因为这个return的临时对象肯定就是“右值”昂!!!
}
shared_ptr<string> ps1 = myfunc();//√!

临时对象一定是一个右值!所以可以将一个临时的unique_ptr指针转换为shared_ptr指针。

运行结果:

 不能将左值的unique_ptr转换为shared_ptr!

 对于:

unique_ptr<string> puns(new string("I Love China!"));
//puns是一个左值!
//shared_ptr<string> ps1 = puns;//❌错误!
shared_ptr<string> ps2 = std::move(puns);

运行调试结果:

        在运行shared_ptr<string> ps2 = std::move(puns);这行代码之前的调试结果:

         在运行shared_ptr<string> ps2 = std::move(puns);这行代码之后的调试结果:

        std::move()函数会将对象(这个左值)变为一个右值,同时将该左值置为空。(人话:就是将这个左值所占据的内存空间的管理权限直接移动给新的对象,原对象对这块内存空间就没有管理权限了--》置空!)

        以上就是我总结的关于智能指针(unique_ptr)之详述、常用操作的笔记。希望你能读懂并且消化完,也希望自己能牢记这些小小的细节知识点,加油吧,我们都在coding的路上~

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Th5.6:智能指针(unique_ptr)之详述1 的相关文章

  • WPF:Prism 对于小型应用程序来说是不是太过分了?

    如果我不将我的应用程序分成不同的模块 否则我会认为 Prism 确实是可行的方法 我应该使用 Prism 吗 我知道 Prism 提供了一个方便的实现ICommand 我可以自己在一页代码中完成 并为我们提供IEventAggregator
  • Wpf TextBlock 中的垂直文本

    是否可以垂直显示 TextBlock 中的文本 以便所有字母彼此堆叠 不使用 LayoutTransform 旋转 还没有人提到使用纯 XAML 垂直堆叠任意字符串的字母 不旋转它们 的明显而简单的方法
  • WPF 处理文本、图像和文件粘贴事件

    我正在开发一个 WPF 应用程序 我想捕获 RichTextBox 输入中的粘贴命令并处理粘贴的文件 为此 我使用以下回调
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • WPF/C# 将自定义对象列表数据绑定到列表框?

    我在将自定义对象列表的数据绑定到ListBox in WPF 这是自定义对象 public class FileItem public string Name get set public string Path get set 这是列表
  • 给图像着色[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我正在尝试着色System Windows Controls Image 该图像包含透明区域 我只是想用颜色给非透明区域着色 例如 图
  • 选择 List 中整周没有休息日的记录 - C#

    我有一个Employee类定义如下 Employee public int Id get set public string Name get set public DateTime WorkDate get set public bool
  • PreviewKeyDown 不会在 ElementHost 中针对 Tab 和箭头键触发

    我在 Winforms ElementHost 中有一个 WPF 窗口 我的窗口上的 Tab 键和箭头键不会触发 KeyDown 和 PreviewKeyDown 事件 KeyUp 和 PreviewKeyUp 似乎工作正常 Preview
  • 如何枚举控件的所有依赖属性?

    我有一些 WPF 控件 例如 文本框 如何枚举该控件的所有依赖属性 如 XAML 编辑器所做的那样 不需要使用反射 恕我直言 这是一个坏主意 因为框架已经为此提供了实用程序类 但它们并不明显找到 以下是基于这篇文章的答案 枚举绑定 http
  • Linq 表达式树 Any() 问题

    您好 我在使用 Any 扩展方法的表达式树时遇到问题 这是我的代码 IQueryable
  • Linq To SQL - 拥有和分组依据

    我下面这个查询工作正常 不过我想使用 Linq 来实现它 select u ID u NAME from Task t join BuildingUser bu ON bu ID BUILDING t ID BUILDING join Us
  • WPF 创建同级窗口并关闭当前窗口

    我需要的是我的窗口类中的这样一个事件处理程序 void someEventHandler object sender RoutedEventArgs e MyNewWindow mnw new MyNewWindow mnw Owner W
  • 创建带有部分的选项卡式侧边栏 WPF

    我正在尝试创建一个带有部分的选项卡式侧边栏 如 WPF 中的以下内容 我考虑过几种方法 但是有没有更简单 更优雅的方法呢 方法一 列表框 Using a ListBox并将 SelectedItem 绑定到右侧内容控件所绑定的值 为了区分标
  • WPF根据数据类型设置样式?

    问题就在这里 我将 TreeView 与几种不同类型的对象绑定 每个对象都是一个节点 有些对象有一个名为 IsNodeExpanded 的属性 当然 有些对象则没有 这是我的风格 现在 问题是当绑定不具有此属性的项目时 我们在输出中收到此错
  • 如何使用 Linq-to-SQL 而无需生成所有类?

    我以前从未在应用程序中使用过 Linq to Sql 但我使用 LinqPad 开发查询 只是想将其粘贴到我的代码中 事情没那么简单 我猜我需要一个DataContext处理连接 但我仍然收到错误 因为视图名称无法识别 Do I have使
  • 主从视图中聚合详细信息值

    我在一些自定义实体中有主从关系 假设我有以下结构 class Master INotifyPropertyChanged public int Id get set property changed implementation publi
  • 如何使取消按钮像“X”按钮一样工作?

    在我的 XAML 文件中 我有一个窗口 我试图将其设置为无论用户单击 X 按钮还是单击 取消 按钮 行为都是相同的 我的缩写代码如下 public partial class Dialog Window private void Windo
  • 使用带有 prism 的 MVVM 在视图之间进行更改

    我是 WPF 新手 但根据我所读到的内容 构建应用程序的正确方法是在同一窗口上切换视图 我的意思是类似于带有菜单和显示视图的工作区的 框架 到目前为止我一直在关注这个http jesseliberty com 2011 01 06 wind
  • 带有空项目的组合框?

    假设我们有一个数据源绑定到数据库中的集合 当然不存在空项 如何添加一个将项目无效到 ComboBox 中 这样第一次加载时用户会看到一个空字符串 我不想将虚拟 空对象添加到集合中 最好在 XAML 中 有什么建议吗
  • 如何在 C#/WPF 中停止动画?

    我有这样的事情 barProgress BeginAnimation RangeBase ValueProperty new DoubleAnimation barProgress Value dNextProgressValue new

随机推荐

  • HDOJ 1052 Tian Ji -- The Horse Racing

    Tian Ji The Horse Racing Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 2
  • Java自定义注解参数ElementType.PARAMETER

    1 创建自定义参数注解 import org springframework core annotation AliasFor import java lang annotation Target ElementType PARAMETER
  • python对字符串使用min和max

    今天日常刷题 看到了一个最长公共前缀比较高级的解法 题目如下 在评论区看到一个比较聪明的解法 class solution def st strs if not strs return str1 min strs str2 max strs
  • nacos频繁挂

    背景 公司使用的nacos 频繁挂 查看日志发现 Java HotSpot TM 64 Bit Server VM 25 144 b01 for linux amd64 JRE 1 8 0 144 b01 built on Jul 21 2
  • word2vec词向量训练及中文文本相似度计算

    本文是讲述如何使用word2vec的基础教程 文章比较基础 希望对你有所帮助 官网C语言下载地址 http word2vec googlecode com svn trunk 官网Python下载地址 http radimrehurek c
  • matlab armax 预测,MATLAB中ARMA模型预测差分问题

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 这是我MATLAB预测风速的程序 程序不是我自己写的 我也是拿来参考自己的毕业作业的 每条程序旁的中文是我自己的理解 我也不知道对不对 程序1 X load C Users asus Deskt
  • 华为OD机试 - 计算礼品发放的最小分组数目(Java)

    题目描述 又到了一年的末尾 项目组让小明负责新年晚会的小礼品发放工作 为使得参加晚会的同事所获得的小礼品价值相对平衡 需要把小礼品根据价格进行分组 但每组最多只能包括两件小礼品 并且每个分组的价格总和不能超过一个价格上限 为了保证发放小礼品
  • vue 和 js 获取 dom节点下的某个元素,然后设置样式

    vue获取dom节点下的类名 然后修改样式 div div class a 提到岁月 你们总说它是长河 流得头也不回 div div class a 少不更事的年纪 我也用过老成口气 念过孔夫子的 逝者如斯乎 不舍昼夜 div div cl
  • 手写数字识别——算法

    识别方法一 基于结构模式 脱机识别 例子 基于基元和七段式数字的手写数字识别 日常生活中经常可以看到用七段式数字表示数字 如电子手表的数字显示等 它用火柴棍拼图的方式能够简单有效的表示出0 9 10个阿拉伯数字 例子 基于三次样条和整体特征
  • css img自适应盒子尺寸

    首先保证图片可以填满 然后纵向居中 img cantainer position relative width 260px height 150px overflow hidden img position absolute top 50
  • 最详细的Java入门完整教程,学Java先收藏了!

    从 1995 年第一个版本发布到现在 Java 语言已经在跌宕起伏中走过了 26 年 最新的 Java 版本也已经迭代到 Java 16 java是有一个庞大的生态系统 它的覆盖范围非常广 而且已经连续十几年位居开发语言的榜首 所以java
  • 浅度学习模块化与解耦

    目录 1 为什么要模块化 2 模块设计原则 3 模块化开发的的优缺点 4 解耦与通信 4 1 公共模块的下层 4 2 面向接口调用 4 3 面向协议的调用 在开篇之前引用一句话 一派是说app开发并不需要什么狗P架构 第二派说我们有自己NB
  • 圈圈教你玩转USB第三版 光盘资料

    下载官网 http service buaapress com cn mzs file detail id 2199 key b2fec916cc9fa216abe6fc836e3f7e35
  • Swift中的‘open‘关键字是什么?

    本文翻译自 What is the open keyword in Swift The ObjectiveC swift file from the standard library contains the following few l
  • C语言基础代码(1)

    C语言是计算机及其相关专业学生必修的语言 我在大一下学期就已经学习了 前段时间 我又将谭浩强编写的C程序设计 也就是我C语言学习的课本看了一遍 温故而知新 受益良多 于是就萌发了一个想法 想将C语言学习当中一些基础的代码做一个总结归纳 在总
  • 牛客专项练习之设计模式

    开头先一句水平有限 仅供参考 有错误可以提醒我改一下 感谢 1 如果需要一个语言解释执行 并且可以将语言中的句子表示为一个抽象语法树的时候 对效率要求不高的情况下 应该选择何种设计模式 题目中的解释二字就告知选项 解释器模式 给定语言 定义
  • Nginx额外篇之一些错误解决办法

    错误1 配置了Nginx 但是打开页面是乱码 解决办法如下 在你个人的sever端添加如下2行 default type text html 设置内容输出内容型为 html htm shtml 三种类型 charset utf 8 设置字符
  • java导出word,红色的单元格背景色显示为黑色

    之前有这个问题 当我用正版office看导出word文件的时候 单元格背景是红色 当我换wps看导出的文件的时候 单元格背景是黑色的 离谱 所以我当初为了省事直接和客户说 请使用正版office 狗头 然后今天闲着没事情 再看ftl模板的时
  • 001问

    偶然间 我的好朋友问起我这个问题 我还真没有好好思考过这个问题 我查了Go语言圣经 知名博客 以及Go中文文档 发现都没有阐述这个问题 后来找来找去也只有下面的解释 for的初始化语句不能是任何类型的语句 必须是 简单语句 短变量声明 就是
  • Th5.6:智能指针(unique_ptr)之详述1

    本小节学习的知识点分别是智能指针 unique ptr 之详述 常用操作 今天总结的知识分为以下2个大点 1 unique ptr概述 常用操作 1 1 常规初始化 unique ptr和new配合 1 2 make unique 函数 2