c++智能指针(4)-- shared_ptr

概述

场景一:   希望指向多个指针管理一片空间

unique_ptr它是不允许两个智能指针管理一片空间的,所以其禁止直接拷贝和赋值(转化为右值可以)。

auto_ptr虽然其允许我们多个智能指针管理一片空间,但是这样的操作对于auto_ptr来说是不安全的,因为一个智能指针释放空间时,是不管别的指针的。

但是,我们有时候是希望,使用多个指针来指向同一片空间的,这样unique_ptr无法实现,auto_ptr又不安全,所以c++11又增加了shared_ptr,它是允许我们使用多个智能指针管理一片空间的。

场景二:  作为容器的类型

前面说到unique_ptr和auto_ptr作为容器的类型的时候,是无法满足容器的特性的(就是两个元素之间赋值),但是shared_ptr是支持的。

 

shared_ptr原理 

智能指针中使用引用计数的方式来判断是否需要释放智能指针指向的动态的空间。

shared_ptr内部使用引用计数的方式,每一片空间都有一个引用计数,每有一个指针指向这片空间,那么其引用计数就会加1,有指针不指向它了,其引用计数就会减1。 


当智能指针管理的空间的引用计数为0的时候,就会释放这块内存。

所以使用shared_ptr指向同一片空间,是不会出现一个释放影响别的指针使用的,因为一个指针不使用,其只会影响引用计数,只有当智能指针释放的时候,空间的引用计数也减为0了,那么就会释放这块空间。(也就是只有一个智能指针管理这块空间时,当智能指针释放,这块空间也就释放了)

 

注意事项(适用于所有智能指针) 

我们不能随便将一块地址让智能指针进行管理,只能将动态开辟的空间让它去管理。

 比如:  int a = 10;

           auto_ptr<int> p1(&a);  // error;


千万注意上面这样的代码,因为我们智能指针的析构函数是使用delete来释放空间的,也就是说其管理的应该是动态开辟的空间,如果像上面那样写,会导致delete释放非堆内存,这显然不对。

 

1. 定义shared_ptr的对象 

  • unique_ptr<类型>  p1(new 空间);  // 类型:  智能指针指向的类型,空间:智能指针管理的空间 
  • std::shared_ptr<int> p1;
    std::shared_ptr<int> p1(NULL);  // 创建指向空的智能指针,注意,此时其引用计数为                                                             0(因为没有指向空间)
  • std::shared_ptr<int> p1(new int());  //  p1直系那个一片空间,引用计数+1
  • 使用auto_ptr,unique_ptr,shared_ptr的临时对象初始化
    std::shared_ptr<int> p1(std::unique_ptr<int> (new int)); // 执行完这行unique_ptr的指针                                                                                             就释放了
    std::shared_ptr<int> p1(std::shared_ptr<int> (new int));
    std::shared_ptr<int> p1(std::auto_ptr<int> (new int));
  •     int a = new int();
        std::shared_ptr<int> p1(&a);

 

2. 多个指针指向同一块空间 

  • 拷贝构造
    std::shared_ptr<int> p1(new int());
    std::shared_ptr<int> p2(p1); 
     
  • 赋值 -- 所以其可以作为容器的类型,其更加符合容器的要求(一个元素可以赋值给另外一个元素)
    std::shared_ptr<int> p1(new int());
    std::shared_ptr<int> p2;
    p2 = p1;


例子:  

std::shared_ptr<int> p1(new int(10));  // p1指向空间,引用计数+1(为1)
{
    std::shared_ptr<int> p2;
    p2 = p1;   // 指针p2和p1指向了同一片空间(引用计数加1(为2)),在大括号结束之后,p2被                           释放,引用计数减1(为1)。
}
std::cout << *p1 << std::endl; // 由于p2释放后引用计数为1,所以空间没有释放,所以此时                                                      访问空间数据没有问题。
当然,当p1析构,那么引用计数就变成0了,那么就释放掉此空间。

 

3. shared_ptr的函数 

1)use_count()函数 

  • long use_count();

我们前面说到,共享指针基于引用计数来实现多个指针管理一片空间的,那我们如何知道当前的指针指向的空间被多少的指针指向。

我们可以使用use_count(),这个函数返回当前指针指向空间的引用计数是多少。 

代码: 
int main(void) {
	std::shared_ptr<int> p1(new int(10));

	{
		std::shared_ptr<int> p2(p1);
		std::cout << p2.use_count() << std::endl;  // 输出2
	}
	std::cout << p1.use_count() << std::endl; // 输出1

	std::cin.get();
}

 

2) unique()函数 

  • bool unique(); // 用来判断,当前指针指向其管理空间的是否只有它(引用计数是否为1),如果是返回true,如果不是返回false。
代码: 
std::shared_ptr<int> p1(new int(10));  
if (p1.unique()) {   // 返回true
    std::cout << "引用计数为1" << std::endl;  // 正常输出
}

 

3)swap(),get(),release()函数 

 

  • T* get(p); // 返回智能指针指向的空间地址
  • void p.reset(地址); // 重新设置智能指针指向的空间地址
  • T* release(p); // 将管理空间的权限重到我们手中

当然这些函数和auto_ptr的用法一样,那里我们进行了详细的描述。 

 

4. 内置类型element_type

表示当前智能指针指向的数据的类型,我们在使用智能指针数据的时候,可以直接使用此类型来统一表示,并不用去关心其具体指向什么类型。 


std::shared_ptr<int>::element_type t = 10;

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML快速入门

HTML简介 HTML&#xff08;超文本标记语言&#xff09;是一种用于创建网页和Web应用程序的标记语言。它由一系列标签组成&#xff0c;每个标签通过尖括号来定义&#xff0c;并用于标记文本、图像、链接和其他内容。HTML标签描述了网页中的信息结构和布局&#xff0c;并定义了文…

[MySQL数据库] 索引与事务

1. 索引 1.1 概念 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针.可以对表中的一列或多列创建索引,并指定索引的类型&#xff0c;各类索引有各自的数据结构实现. 1.2 作用 数据库中的表、数据、索引之间的关系&#xff0c;类似于书架上的图书、书籍…

【Redis】面试题汇总

Redis什么是Redis、使用场景有哪些Redis 为什么这么快&#xff1f;Redis 数据类型及使用场景五种常见的 Redis 数据类型是怎么实现&#xff1f;Redis是单线程吗Redis 采用单线程为什么还这么快&#xff1f;Redis 如何实现数据不丢失&#xff1f;Redis 如何实现服务高可用&#…

【复习笔记】FreeRTOS(六) 队列操作

本文是FreeRTOS复习笔记的第六节&#xff0c;队列操作。 上一篇文章&#xff1a; 【复习笔记】FreeRTOS(五)时间片调度 文章目录 1.队列操作1.1.队列操作过程1.2.队列操作常用的API函数 二、实验设计三、测试例程四、实验效果 1.队列操作 队列是为了任务与任务、任务与中断之间…

极狐GitLab x LigaAI,AI 时代研发提效新范式

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 近日&#xff0c;极狐GitLab 和 LigaAI 宣布合作&#xff0c;双…

分布式锁设计

一、为什么需要分布式锁 1.1 单体项目同步实现 在单进程&#xff08;启动一个jvm&#xff09;的系统中&#xff0c;当存在多个线程可以同时改变某个变量&#xff08;可变共享变量&#xff09;时&#xff0c;就需要对变量或代码块做同步&#xff0c;使其在修改这种变量时能够线…

vue2中props属性设置一个对象或数组的默认值

在Vue.js中&#xff0c;如果您想要为一个props属性设置一个对象或数组的默认值&#xff0c;您应该使用一个函数来返回这个默认值。这是因为对象和数组是引用类型&#xff0c;直接将它们作为默认值可能会导致预设的默认值被所有实例共享&#xff0c;这不是我们想要的结果。 下面…

zabbix 自定义模板,邮件报警,代理服务器,自动发现与自动添加及snmp

目录 一. 自定义监控内容 1. 在客户端创建自定义 key 2. 在 web 页面创建自定义监控项模块 2.1 创建模板 2.2 创建应用集 2.3 创建监控项 2.4 创建触发器 2.5 创建图形 2.6 将主机与模板关联起来 登录测试 2.7 设置邮件报警 测试邮件报警 3. nginx 服务状况的检测…

Vue中SourceMap的使用方法详解

目录 一、概述 二、使用方法 三、生成SourceMap 四、优化 五、结语 一、概述 Vue.js是一套构建用户界面的渐进式框架&#xff0c;通过HTML模板或者直接写render函数可以快速开发单页应用。在开发过程中&#xff0c;很多时候我们需要调试代码&#xff0c;追踪错误。Vue官方…

Linux:调试器 - gdb

Linux&#xff1a;调试器 - gdb gbd基本概念gbd调试浏览断点运行变量 gbd基本概念 GDB (GNU Debugger) 是一个强大的命令行调试工具,用于调试各种编程语言(如C、C、Java、Python等)编写的程序。使用 gdb可以帮助开发人员更快地定位和修复程序中的缺陷,提高代码质量和开发效率。…

Python介绍(未完)

文章目录 Python 背景知识Python 是谁创造的&#xff1f;Python 可以用来干什么&#xff1f;Python 的优缺点 搭建 Python 环境安装 Python搭建 PyCharm 环境新工具到手&#xff0c;赶紧试试中文设置第一个Python程序 Python基础语法基础语法&#xff08;1&#xff09;常量和表…

Error : java 错误 : 不支持发行版本5 ( 完美解决)

解决方案 1. 原因 idea的默认配置JDK版本与当前项目所需版本不一样 方案一&#xff08;每一个项目可能都要配置一遍&#xff09; Ctrlshitalts 打开项目结构&#xff0c;设置项目所需的JDK版本&#xff0c;本项目需要JDK8 Modules的JDK版本为5&#xff0c;这时就会报Error …

最大公约数和最小公倍数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>//实现最大公约数函数&#xff1b; int max(int x, int y) {//初始化变量值&#xff1b;int judge 1;//运算&#xff1b;judge x %…

Ubuntu 23.10.1 nginx源码安装

注&#xff1a;以下所有命令均在root管理员模式下&#xff0c;若不是&#xff0c;请在所有命令前加sudo 1、安装依赖库 1.1、安装gcc g的依赖库 apt-get install build-essential apt-get install libtool1.2、安装pcre依赖库 apt-get update apt-get install libpcre3 lib…

剑指Offer题目笔记33(并查集)

面试题116&#xff1a; 解决方案&#xff1a; ​ 一个班级可以包含一个或多个朋友圈&#xff0c;对应的图中可能包含一个或多个子图&#xff0c;每个朋友圈对应一个子图。因此&#xff0c;这个问题可以转化为如何求图中子图的数目。图的搜索算法可以用来计算图中子图的数目。扫…

企业Linux特殊权限位/为什么会存在SUID?/企业环境测试(原理剖析)-4989字解析

企业高薪思维&#xff1a; 坚持很难&#xff0c;优秀的人才是少数&#xff0c;很重要 坚持不下去&#xff0c;问自己想要什么&#xff1f; 问问自己想要好的生活状态&#xff1f;问自己有背景吗&#xff1f;你学历是亮点吗&#xff1f;有钱没&#xff0c;你也就是一般家庭&…

selenium 下载文件取消安全下载的方法

问题描述 我要从一个网站上下载文件&#xff0c;谷歌浏览器总是自动阻止下载&#xff0c;并询问我是否保留。 可是&#xff0c;我想要的是不要询问&#xff0c;默认下载即可。 运行环境 OS: macOSselenium: 4.19.0python: 3.10.11Chrome: 124.0.6367.62selenium chromedrive…

工会排队模式:创新营销的双赢之道

工会排队模式全面解读 在当今数字化营销的大潮中&#xff0c;促销方式层出不穷&#xff0c;但能真正抓住消费者眼球并带来双方共赢的模式并不多见。而工会排队模式便是在这样的背景下崭露头角&#xff0c;它巧妙地融合了工会积分、奖金池与排队机制&#xff0c;为消费者与商家…

linux进阶篇:重定向和管道操作

Linux中的重定向和管道操作 llinux中的三种IO设备&#xff1a; 标准输入&#xff08;STDIN&#xff09;,文件描述符号为&#xff1a;0&#xff0c;默认从键盘获取输入 标准输出&#xff08;STDOUT&#xff09;,文件描述符号位&#xff1a;1&#xff0c;默认输出到显示终端 标准…

java宠物领养系统的设计与实现(springboot+mysql+源码)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的宠物领养系统的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于Spring Bo…
最新文章