C++-第二十章:智能指针

news2025/3/6 21:33:38

目录

第一节:std::auto_ptr

第二节:std::unique_ptr

第三节:std::shared_ptr

第四节:std::shared_ptr的缺陷

        4-1.循环引用

         4-2.删除器

下期预告:


        智能指针的作用是防止指针出作用域时忘记释放内存而造成内存泄漏,智能指针重载了[]、*、->来模拟原生指针的行为,智能指针包含在<memory>中。

        智能指针有几种,各有其特点。

第一节:std::auto_ptr

        std::auto_ptr 的特点是没有拷贝构造和拷贝赋值,只有移动构造和移动赋值。所以用一个智能指针给另一个智能指针传参时,实际上是把管理权转移了:

int main()
{
	std::auto_ptr<int> ptr1(new int(1));
	std::auto_ptr<int> ptr2 = ptr1;
	std::cout << ptr1.get() << std::endl; // 打印原生指针的内容
	std::cout << ptr2.get() << std::endl; // 打印原生指针的内容
	return 0;
}

  

        这样 ptr1 就指向nullptr,它是不安全的,很容易出现野指针的解引用。

        但是它的好处是不容易出现两个std::auto_ptr管理同一块空间,出作用域时两次释放同一空间。

 

第二节:std::unique_ptr

        unique意为单一的,它没有拷贝构造、赋值构造、移动构造、移动赋值。相比于std::auto_ptr更加安全。

第三节:std::shared_ptr

        shared意为分享,它运行进行拷贝构造、赋值构造、移动构造、移动赋值。

        为了解决多次释放内存的问题,它引入了一个计数器,这个计数器是静态变量,被指向同一空间的std::shared_ptr 共享。只要创建一个智能指针时,计数器就会加1,智能指针析构时会判断计数器是否为1,如果不是,说明自己还不是最后一个管理该内存的指针,就不会释放内存,如果是,就会释放内存。

        std::shared_ptr 除了直接使用原生指针赋值,还可以使用std::make_shared进行赋值:

std::shared_ptr<int> ptr(std::make_shared<int>(1));

        使用它的优势是让内存碎片更小,因为new来构造智能指针时,要分配两次内存:(1)智能指针对象(2)指针指向的内存空间。

        std::make_shared,会一次性申请足够的内存用来存放智能指针对象和指针指向的内存空间,内存只分配了一次,所以内存碎片更小。

第四节:std::shared_ptr的缺陷

        4-1.循环引用

        std::shared_ptr 的计数器的存在,使得最后一个智能指针才释放内存,但是当最后两个智能指针的析构互为对方析构的前提时,就会导致内存泄漏:

 

#include <memory>

class Node
{
public:
    std::shared_ptr<Node> _prev = nullptr;
    std::shared_ptr<Node> _next = nullptr;
};

int main()
{
    auto n1 = std::make_shared<Node>();
    auto n2 = std::make_shared<Node>();
    n1->_next = n2;  // n1 持有 n2 的 shared_ptr
    n2->_prev = n1;  // n2 持有 n1 的 shared_ptr
    return 0;
}

        如上图所示,智能指针p1、p2分别指向两个相互指向的节点,此时它们的引用计数都是2。

        p1释放内存的前提是p2的_prev先析构,

        p2的_prev析构的前提是p2先释放内存,

        p2释放内存前提是p1的_next先析构,

        p1的_next析构的前提是p1释放内存,

        这样就构成闭环了,谁也释放不了。

        解决方法是将_next和_prev的类型都改成std::weak_ptr,它是一种资源的弱引用,提供一种可观察而非拥有的访问方式。

        它的特点是不直接管理资源的释放,引用计数也不会增加,将_next、_prev改成std::weak_ptr类型即可打破循环引用。

         4-2.删除器

        智能指针默认的析构方式是对指针进行delete操作,这对文件指针无能为力,因为文件指针释放内存的方式是fclose,此时可以定制一个删除器传入智能指针:

 

std::shared_ptr<FILE> ptr(fopen("test.txt","w"),[](FILE* _ptr){fclose(_ptr);});

        ptr 在析构时就会调用传入的可调用对象关闭文件指针了。

下期预告:

         第二十一章是C++的最后一章,将介绍类的特殊设计。

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

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

相关文章

chrome Vue.js devtools 提示不支持该扩展组件,移除

可能是版本不兼容&#xff0c;可以重新安装&#xff0c;推荐网址极简插件官网_Chrome插件下载_Chrome浏览器应用商店 直接搜索vue&#xff0c;下载旧版&#xff0c;vue2、vue3都支持&#xff0c;上面那个最新版本试了下&#xff0c;vue2的肯定是不能用

C# 中的Action和Func是什么?Unity 中的UnityAction是什么? 他们有什么区别?

所属范围&#xff1a;Action 和 Func 是 C# 语言标准库中的委托类型&#xff0c;可在任何 C# 项目里使用&#xff1b;UnityAction 是 Unity 引擎专门定义的委托类型&#xff0c;只能在 Unity 项目中使用。 返回值&#xff1a;Action 和 UnityAction 封装的方法没有返回值&…

Versal - XRT(CPP) 2024.1

目录 1.简介 2. XRT 2.1 XRT vs OpenCL 2.2 Takeways 2.3 XRT C APIs 2.4 Device and XCLBIN 2.5 Buffers 2.5.1 Buffer 创建 2.5.1.1 普通 Buffer 2.5.1.2 特殊 Buffer 2.5.1.3 用户指针 Buffer 2.5.2 Data Transfer 2.5.2.1 read/write API 2.5.2.2 map API 2…

windows下安装Open Web UI

windows下安装openwebui有三种方式,docker,pythonnode.js,整合包. 这里我选择的是第二种,非docker. 非Docker方式安装 1. 安装Python&#xff1a; 下载并安装Python 3.11&#xff0c;建议安装路径中不要包含中文字符&#xff0c;并勾选“Add python 3.11 to Path”选项。 安…

【自用】NLP算法面经(4)

一、deepseek 1、MLA &#xff08;1&#xff09;LLM推理过程 prefill阶段&#xff1a;模型对全部的prompt tokens一次性并行计算&#xff0c;最终生成第一个输出token。decode阶段&#xff1a;每次生成一个token&#xff0c;直到生成EOS&#xff08;end-of-sequence&#xf…

LeetCode热题100JS(20/100)第四天|​41. 缺失的第一个正数​|​73. 矩阵置零​|​54. 螺旋矩阵​|​48. 旋转图像​

41. 缺失的第一个正数 题目链接&#xff1a;41. 缺失的第一个正数 难度&#xff1a;困难 刷题状态&#xff1a;1刷 新知识&#xff1a; 解题过程 思考 示例 1&#xff1a; 输入&#xff1a;nums [1,2,0] 输出&#xff1a;3 解释&#xff1a;范围 [1,2] 中的数字都在数组中…

【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程

更多银河麒麟操作系统产品及技术讨论&#xff0c;欢迎加入银河麒麟操作系统官方论坛 https://forum.kylinos.cn 了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer…

开源架构与人工智能的融合:开启技术新纪元

最近五篇文章推荐&#xff1a; 开源架构的自动化测试策略优化版&#xff08;New&#xff09; 开源架构的容器化部署优化版&#xff08;New&#xff09; 开源架构的微服务架构实践优化版&#xff08;New&#xff09; 开源架构中的数据库选择优化版&#xff08;New&#xff09; 开…

【弹性计算】弹性裸金属服务器和神龙虚拟化(二):适用场景

《弹性裸金属服务器》系列&#xff0c;共包含以下文章&#xff1a; 弹性裸金属服务器和神龙虚拟化&#xff08;一&#xff09;&#xff1a;功能特点弹性裸金属服务器和神龙虚拟化&#xff08;二&#xff09;&#xff1a;适用场景弹性裸金属服务器和神龙虚拟化&#xff08;三&a…

计算机毕业设计SpringBoot+Vue.js保险合同管理系统(源码+文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

58、深度学习-自学之路-自己搭建深度学习框架-19、RNN神经网络梯度消失和爆炸的原因(从公式推导方向来说明),通过RNN的前向传播和反向传播公式来理解。

一、RNN神经网络的前向传播图如下&#xff1a; 时间步 t1: x₁ → (W_x) → [RNN Cell] → h₁ → (W_y) → y₁ ↑ (W_h) h₀ (初始隐藏状态) 时间步 t2: x₂ → (W_x) → [RNN Cell] → h₂ → (W_y) → y₂ ↑ (W_h) h₁ 时间…

bge-large-zh-v1.5 与Pro/BAAI/bge-m3 区别

ge-large-zh-v1.5 和 Pro/BAAI/bge-m3 是两种不同的模型&#xff0c;主要区别在于架构、性能和应用场景。以下是它们的对比&#xff1a; 1. 模型架构 bge-large-zh-v1.5&#xff1a; 基于Transformer架构&#xff0c;专注于中文文本的嵌入表示。 参数量较大&#xff0c;适合处…

lamp平台介绍

一、lamp介绍 网站&#xff1a; 静态 动态 php语言 .php 作用&#xff1a;运行php语言编写动态网站应用 lamp Linux Apache MySQL PHP PHP是作为httpd的一个功能模块存在的 二、部署lamp平台 1、测试httpd是否可正常返回PHP的响应 2、测试PHP代码是否可正常连接数据…

Windows10系统构建本地安全私有化的个人知识库——采用DeepSeek+RAGFlow

一、为什么要构建本地私有化个人知识库 1.1、自身需求 1、需要相关隐私资料内容的安全保护可控; 2、需要根据自身的隐私资料内容构建出个性化的知识库; 一些常见的业务场景如:①希望我们的智能助手可以根据公司的管理制度回答问题,让员工可以随时了解公司相关制度内容信息;…

Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案

Linux: Centos7 Cannot find a valid baseurl for repo: base/7/x86_64 解决方案 问题背景&#xff1a; 执行yum update出现如下报错 排查虚拟机是否联网&#xff1a; ping -c 4 www.baidu.com 可以看到网络链接没有问题 解决方案&#xff1a; 原因是国外的镜像源有问题&am…

Java 大视界 -- Java 大数据在智能金融反欺诈中的技术实现与案例分析(114)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

每日OJ_牛客_游游的字母串_枚举_C++_Java

目录 牛客_游游的字母串_枚举 题目解析 C代码 Java代码 牛客_游游的字母串_枚举 游游的字母串 描述&#xff1a; 对于一个小写字母而言&#xff0c;游游可以通过一次操作把这个字母变成相邻的字母。a和b相邻&#xff0c;b和c相邻&#xff0c;以此类推。特殊的&#xff0…

示例:在WPF中如何使用Segoe MDL2 Assets图标和使用该图标的好处

一、目的&#xff1a;分享在WPF中如何使用Segoe MDL2 Assets图标和使用该图标的好处 在WPF中使用Segoe MDL2 Assets字体&#xff0c;可以通过设置控件的FontFamily属性来实现。Segoe MDL2 Assets是一个包含许多图标的字体&#xff0c;通常用于Windows应用程序的图标显示。 二、…

h5 IOS端渐变的兼容问题 渐变实现弧形效果

IOS端使用渐变的时候有兼容问题 以下是问题效果&#xff0c;图中黑色部分期望的效果应该是白色的。但是ios端是下面的样子…… 安卓pc 支持&#xff1a; background-image: radial-gradient(circle 40rpx at 100% 0, #f3630c 40rpx, rgb(255, 255, 255) 50%);安卓pc ios支持…

Libgdx游戏开发系列教程(4)——显示中文文字

目录 2种方法优缺点 BitmapFont FreeTypeFont 方法1 使用BitmapFont 1.下载hiero工具 2.生成fnt文件 3.代码使用 测试效果 方法2 使用FreeType 1.依赖引入 2.代码使用 测试效果 使用疑问点 这里主要介绍关于在Libgdx显示文字的2种方法 本文代码示例采用kotl…