[C++] 初识 智能指针

标题:[C++] 初识 智能指针

@水墨不写bug



目录

一、前言

二、智能指针

1. 什么是RAII?

2.智能指针分类

 三、智能指针简介

1.std::auto_ptr

2.std::unique_ptr

3.std::shared_ptr


正文开始:

一、前言

        C++智能指针的出现是有一定的背景的:

        Java有专属的GC(垃圾回收功能),这样一来可以在一定程度上解放解放程序员的关于内存方面的思考与手动设计,但GC等特点也是Java相对于C++效率较低的原因。在使用C++编程时,需要时刻注意内存的管理,但是尽管我们时刻都记得要注意内存的管理逻辑,在有一些场景,内存泄漏时有发生,比如下边这样的一个场景:

#include<iostream>
#include<string>
using namespace std;double div(double a, double b)
{if (b == 0)throw string("div by zero");return a / b;
}
void func()
{int* parr1 = new int[10];   // 一int* parr2 = new int[10];   // 二//...double a, b;cin >> a >> b;cout << div(a,b) << endl;   // 三delete[] parr1;delete[] parr2;
}
int main()
{try {func();}catch (string s){cout << s << endl;}catch (...){cout << "unknown err" << endl;}return 0;
}

        在上述场景中,有三个地方可能会抛出异常:如果一处抛异常——则不用释放空间;如果二处抛异常——则需要只释放parr1;如果三处抛异常——则需要释放parr1和parr2。

        这些逻辑比较复杂,为了处理这些场景下复杂的内存管理,C++引入了智能指针。

二、智能指针

1. 什么是RAII?

           C++中的RAII(Resource Acquisition Is Initialization,资源获取即初始化)是一种资源管理技术,它的核心思想是将资源的获取(Acquisition)与对象的初始化(Initialization)结合起来,并通过对象的生命周期来管理资源的使用期。一旦对象被创建,资源就被自动获取;当对象生命周期结束时(例如,对象被销毁时),其析构函数会自动释放或归还资源

借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:


        1.不需要显式地释放资源。
        2.采用这种方式,对象所需的资源在其生命期内始终保持有效
 

         智能指针的实现思路及原理就是RAII的思想。


2.智能指针分类

         目前常用的智能指针有如下几种:

        std::auto_ptr:C++98版本的库中就提供了auto_ptr的智能指针。(不建议使用)
        std::unique_ptr:unique_ptr的实现原理:简单粗暴的防拷贝。
        std::shared_ptr:C++11中开始提供更靠谱的并且支持拷贝的shared_ptr。

 三、智能指针简介

        其实智能指针的基本原理的实现并不困难,就是把一个指针类中,写好构造和析构就可以正常使用了——当前函数栈桢退出,局部变量就会自动销毁。不同的是不同智能指针对于拷贝构造和赋值重载的处理是不同的,而其他接口的处理基本是相同的。

1.std::auto_ptr

        auto_ptr的实现原理:管理权转移。

        std::auto_ptr是比较老的智能指针类型,它可以拷贝构造,但是拷贝构造不是意味着构造了一个新的指针,而是将管理权转移到了新的指针;赋值重载会把原资源释放,把新资源转移到被赋值的指针中。


#include<memory>
#include<iostream>
using namespace std;
int main()
{auto_ptr<int> ap(new int[10]);auto_ptr<int> ap1(ap);if (ap.get() == nullptr)cout << "权限转移:ap->ap1" << endl;auto_ptr<int> ap2;ap2 = ap1;if(ap1.get() == nullptr)cout << "权限转移:ap1->ap2" << endl;return 0;
}
权限转移:ap->ap1
权限转移:ap1->ap2

 


2.std::unique_ptr

        unique_ptr的实现原理:简单粗暴的防拷贝。

        强行将赋值重载和拷贝构造设置为 无法调用:具体可能是 直接加上 = delete ;或者是只声明不实现,并且放在私有。
        其余部分接口的使用与auto_ptr 基本一致。

 


3.std::shared_ptr

        shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。

引用计数原则: 

         1. shared_ptr在其内部,给每个资源都维护了着一份计数p_count,用来记录该份资源被几个指针维护。
        2. 在对象(指针)被销毁时(也就是析构函数调用时),就说明这个对象(指针)不维护该资源了,对象的引用计数减一。
        3. 如果引用计数减到0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
        4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。

         shared_ptr由于通过引用计数实现,其使用方法最接近普通指针,所以这里不再举例如何使用。我们仅仅需要对其几个常用接口熟悉即可。

 std::shared_ptr文档


对于以上的三种智能指针,其底层实现我们暂时不涉及,本篇只设计其思想与使用方法。 


完~

未经作者同意禁止转载 

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

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

相关文章

今天你City了吗?维乐Angel Revo带你穿梭都市自由随风~

当7月的热浪在都市中翻滚&#xff0c;你是否渴望逃离钢筋水泥的束缚&#xff0c;寻找一片属于自己的绿意盎然&#xff1f;今天你City了吗&#xff1f;快带上VELO Angel Revo一起抓住夏日的尾巴&#xff0c;用一场骑行与这座城市的风景共舞&#xff01;      轻巧出行&#…

Centos安装Jenkins教程详解版(JDK8+Jenkins2.346.1)

本教程基于 JDK8 和 Jenkins2.346.1 JDK安装 下载OpenJDK8文件 wget https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/linux/OpenJDK8U-jdk_x64_linux_hotspot_8u422b05.tar.gz解压到指定目录 # 创建目录 mkdir -p /usr/local/software# 解压文件到指定目录&#…

linux-基础知识1

简单命令 init 0 关机 int 6 重启 pwd 查看当前所在目录&#xff0c; cd切换目录 ls 列出目录下的内容 clear 清屏 date 查看时间 路径 linux表示硬件设备的文件在dev目录 /tmp是临时目录&#xff0c;可以创建目录和文件&#xff0c;但不能保证安全 df查看文件系统…

oracle共享池(shared pool):一、工作原理、组成部分 二、软硬解析过程

文章目录 oracle整体结构图共享池&#xff08;shared pool&#xff09;shared pool的作用shared pool的组成查询 shared pool 各组成部分大小硬解析和软解析 oracle整体结构图 共享池&#xff08;shared pool&#xff09; shared pool的作用 1、 将 sql 语句解析成执行计划 …

【Node】【2】创建node应用

创建node应用 node应用&#xff0c;不仅可以实现web应用&#xff0c;也能实现http服务器。 如果是php写后端&#xff0c;还需要有http服务器&#xff0c;比如apache 或者 nginx。 但是现在主流都是java写后端&#xff0c;也可以像 Node.js 一样用于实现 Web 应用和 HTTP 服务…

easypoi模板导出word多页导出加强版

说明 上一篇文章提到多页导出&#xff0c;但是后边发现一个问题&#xff0c;如果用同一个模板导出多页内容&#xff0c;我们去获取多页内容的时候&#xff0c;会发现全部都一样&#xff0c;举个例子&#xff1a; XWPFDocument document WordExportUtil.exportWord07(outputU…

有限差分学习笔记

有限差分介绍 ​ 在数学中&#xff0c;有限差分法&#xff08;finite-difference methods&#xff0c;简称FDM&#xff09;&#xff0c;是一种微分方程数值方法&#xff0c;是通过有限差分来近似导数&#xff0c;从而寻求微分方程的近似解。 由泰勒展开式的推导 显式方…

C# 项目管理CLI常用命令

Command Line Interface (CLI) .NET Command Line Interface (CLI) 是一个跨平台的工具链&#xff0c;用于开发、构建、运行和发布基于 .NET Core 和 .NET 5 应用程序。以下是一些常用的 .NET CLI 命令及其简要说明&#xff1a; 创建新项目 dotnet new <template> [-n|…

选择搜索引擎进行搜索

<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>选择搜索引擎进行搜索</title><script>function searchSelectedEngine() {var keyword document.getElementById(keyword).value;var engine document.getEl…

【PyTorch】关于Tensorboard的简单使用

前提文章目录 【PyTorch】深度学习PyTorch环境配置及安装【详细清晰】 【PyTorch】深度学习PyTorch加载数据 文章目录 前提文章目录SummaryWriter使用add_image()的使用&#xff08;常用来观察训练结果&#xff09;利用Tensorboard观察图片 SummaryWriter使用 from torch.util…

手把手教你用vite+React18+TS+redux+prettier+eslint+Ant打造企业级前端项目

通过这篇文章你可以学到 如何使用使用 webpack 搭建项目如何在 webpack中集成 typescript如何在 webpack 中集成 React Router 和 Redux如何使用 React 的组件库 Ant Design如何在项目中集成 eslint 和 prettier 保证代码质量如何为团队开发专属的项目模板 环境依赖版本 nod…

Hive SQL语言

目录 Hive SQL之数据库与建库 create database :创建数据库 use database :选择特定的数据库 drop database :删除数据库 Hive SQL之表与建表 create table : 创建表 分隔符指定语法 Hive SQL-DML-Load加载数据 Load语法功能 语法规则之filepath 语法规则之LOCAL …

spring揭秘09-aop03-aop织入器织入横切逻辑与自动织入

文章目录 【README】【1】spring aop的织入【1.1】使用ProxyFactory 作为织入器【1.2】基于接口的代理&#xff08;JDK动态代理&#xff0c;目标类实现接口&#xff09;【补充】 【1.2】基于类的代理&#xff08;CGLIB动态代理&#xff0c;目标类没有实现接口&#xff09;【1.2…

数据缓存软件Redis推出Redis 8 这更改许可证后首个重大版本更新

2024 年 3 月流行的数据库缓存应用 Redis 宣布修改开源许可证&#xff0c;此次修改许可证的目的本质上就是避免大型云计算公司白嫖&#xff0c;例如亚马逊的 AWS 等。AWS 等云计算服务商基于 Redis 推出托管服务并向客户收费&#xff0c;作为开发商 Redis 并没有获得收益&#…

vue的事件修饰符、数组变化侦测、计算属性、class绑定、style绑定

一、事件修饰符 功能&#xff1a;用于简化代码。 .stop 阻止事件冒泡.prevent 阻止默认事件.once.enter 两种使用方式&#xff1a; e.stopPropagation(); //第一种 click.stop"clickP" //第二种 二、数组变化侦测 分为两类&#xff1a; 1、能够引起UI的自动…

如何从头开始编写一个简单的 RPC 协议(手写 Dubbo 的自定义协议)

1. 设计协议格式 首先&#xff0c;需要定义协议的数据包格式&#xff0c;这通常包括头部&#xff08;Header&#xff09;和主体&#xff08;Body&#xff09;两部分。 Header&#xff1a;存储协议的元数据&#xff0c;例如消息类型、序列化方式、请求 ID 等。 Magic Number (2…

阿里云CentOs ClickHouse安装

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; ClickHouse安装目录 前言…

etcd 的Put请求处理

在介绍etcdctl的内容中&#xff0c;我们知道了etcdctl实际上是向etcd服务端执行了grpc请求获取对应的结果&#xff0c;这一篇主要介绍当向etcd服务端执行Get/Put指令的时候究竟做了哪些工作。 Client发出请求 Put指令和之前介绍到的Get指令类似&#xff0c;通过grpc client发…

easypoi模板导出word并且合并行

导出流程 引入依赖制作模板合并导出 引入依赖 <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.1.2</version> </dependency>制作模板 合并行是备注那一列&#xff0c;这一列…

MongoDB如何时间范围查询

MongoDB作为一个高性能、开源、无模式的文档型数据库&#xff0c;广泛应用于各种需要灵活数据模型的应用场景中。在处理与时间相关的数据时&#xff0c;MongoDB提供了强大的查询能力&#xff0c;允许我们轻松地进行时间范围查询。本文将详细介绍如何在MongoDB中执行时间范围查询…