第7章 Page446~449 7.8.9智能指针 std::unique_ptr

2024-02-16 13:36

本文主要是介绍第7章 Page446~449 7.8.9智能指针 std::unique_ptr,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

“unique_ptr”是“独占式智能指针”

名字透露身份,“unique_ptr”是“独占式智能指针”。使用它管理前面的O类指针:

演示1:

例中 p 是一个智能指针。其中的“<O>”指明它所指向的数据类型是“O”。除了创建方法不太一样,以及不用手工释放之外,智能指针使用上和它所管理的裸指针基本一样。

如果健忘而负责任的程序员,忘了p是智能指针,写出“delete p”这样的代码,也不用怕,编译器会就出这个错误。

例中的裸指针同样没有名字,在调用智能指针对象的构造函数是,直接使用new生成。这是推荐的做法,这样做的好处是,防止有人故意捣乱。

构建“unique_ptr”对象是,只能采用“构造式初始化”,不允许采用“赋值式初始化”

如果手头上确实已经有了一个裸指针,临时需要交给智能指针来管理,也是支持的:

O* po = new O();
std::unique_ptr <O> p(po);

这里有个细节,即构建“unique_ptr”对象是,只能采用“构造式初始化”,不允许采用“赋值式初始化”的语法:

std::unique_ptr <O> p2 = new O();//编译出错
O* po = new O();
std::unique_ptr <O> p = po; //同样编译出错

这是刻意的设计,不允许将一个裸指针使用“=”赋值给智能指针。良好的智能指针就是这样一个纠结的设计:既要让它用起来就像一个裸指针,又要在关键的地方提醒一下你,它不是一个真的指针

智能指针也可以有“空指向”的状态,构建时不传入裸指针即可:

std::unique_ptr <O> p; //空指向的智能指针
if(p == nullptr) //成立
{cout << "p is a nullptr" << endl;
}
if(!p)//也成立
{cout << "not p" << endl;
}

演示2:

以上都是让智能指针尽量用起来像裸指针的设计。背后的实现手段还是“重载操作符”。

智能指针当然可以改变指向,

只是同样不能使用“=”将裸指针赋给智能指针右值必须同样是智能指针

std::unique_ptr <O> p; //空指向的智能指针
...
p = std::unique_ptr <O> (new O);//不能省略为“p = new O”

但是这样写显得很冗长,可以改用“unique_ptr”带参版“reset(...)”的方法,用于改变一个“unique_ptr”的指向:

O* src1 = new O;
O* src2 = new O;
std::unique_ptr <O> p(src1); //先管理src1
...
p.reset(src2); //改为管理src2,改之前,src1将被释放

演示3:

改变一个“unique_ptr”的指向,如果该智能指针不是空指向,会先释放原来管理的裸指针,再接管新的裸指针。这中间隐藏了一个风险,即新指向和旧指向,必须确保不是同一个对象:

O* o = new O;
std::unique_ptr <O> p(o); //p管理着o
p = std::unique_ptr <O>(o); //p改变指向,但其实还是指向o。

003行执行过程是这样的:在改变指向之前,p要先干掉当前所管理的裸指针,也就是o。然后再管理新的裸指针,不幸的是,这个所谓的“新”的裸指,仍然是o,刚刚被干掉的o。编译器无法帮我们识别这样的问题。

“unique_ptr”的独占性:

一个裸指针不能由多个“std::unique_ptr”管理,但编译器挡不住程序员刻意将一个裸指针交给多个“unique_ptr”管理,编译器无法阻止你干出“一女多嫁”的事情:

O* o = new O; //一个裸指针
std::unique_ptr <O> p1(o); //交给p1管
std::unique_ptr <O> p2(o); //又交给p2管

错误将在运行时发生,本例中由于O结构没有任何成员数据,所以发生这个错误的程序可能不会挂掉,但错误确实发生了,能够从屏幕输出o被释放两次

演示4:

能不能“改嫁”呢?

O* o = new O; //还是一个裸指针
std::unique_ptr <O> p1(o); //先交给p1
std::unique_ptr <O> p2 = p1; //然后由p1转交个p2?
//std::unique_ptr <O> p2(p1); //同上,但使用更正规构造式初始化

这篇关于第7章 Page446~449 7.8.9智能指针 std::unique_ptr的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/714678

相关文章

Python实现word文档内容智能提取以及合成

《Python实现word文档内容智能提取以及合成》这篇文章主要为大家详细介绍了如何使用Python实现从10个左右的docx文档中抽取内容,再调整语言风格后生成新的文档,感兴趣的小伙伴可以了解一下... 目录核心思路技术路径实现步骤阶段一:准备工作阶段二:内容提取 (python 脚本)阶段三:语言风格调

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

Java Optional避免空指针异常的实现

《JavaOptional避免空指针异常的实现》空指针异常一直是困扰开发者的常见问题之一,本文主要介绍了JavaOptional避免空指针异常的实现,帮助开发者编写更健壮、可读性更高的代码,减少因... 目录一、Optional 概述二、Optional 的创建三、Optional 的常用方法四、Optio

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

使用Python实现表格字段智能去重

《使用Python实现表格字段智能去重》在数据分析和处理过程中,数据清洗是一个至关重要的步骤,其中字段去重是一个常见且关键的任务,下面我们看看如何使用Python进行表格字段智能去重吧... 目录一、引言二、数据重复问题的常见场景与影响三、python在数据清洗中的优势四、基于Python的表格字段智能去重

Spring AI集成DeepSeek三步搞定Java智能应用的详细过程

《SpringAI集成DeepSeek三步搞定Java智能应用的详细过程》本文介绍了如何使用SpringAI集成DeepSeek,一个国内顶尖的多模态大模型,SpringAI提供了一套统一的接口,简... 目录DeepSeek 介绍Spring AI 是什么?Spring AI 的主要功能包括1、环境准备2

Spring AI与DeepSeek实战一之快速打造智能对话应用

《SpringAI与DeepSeek实战一之快速打造智能对话应用》本文详细介绍了如何通过SpringAI框架集成DeepSeek大模型,实现普通对话和流式对话功能,步骤包括申请API-KEY、项目搭... 目录一、概述二、申请DeepSeek的API-KEY三、项目搭建3.1. 开发环境要求3.2. mav

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

Python3脚本实现Excel与TXT的智能转换

《Python3脚本实现Excel与TXT的智能转换》在数据处理的日常工作中,我们经常需要将Excel中的结构化数据转换为其他格式,本文将使用Python3实现Excel与TXT的智能转换,需要的可以... 目录场景应用:为什么需要这种转换技术解析:代码实现详解核心代码展示改进点说明实战演练:从Excel到

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.