[C/C++]智能指针是什么?实现原理是什么?

智能指针

        智能指针是C++提供的一种资源管理工具,用于自动管理动态分配的内存,避免手动调用 new delete 时可能出现的内存泄漏、悬挂指针等问题。智能指针通过封装原始指针,并在适当的时候自动释放资源,从而简化了内存管理。

    智能指针在C++11版本之后提供,包含在头文件<memory>中,主要包括以下几种shared_ptr、unique_ptr、weak_ptr:

std::unique_ptr

独占所有权的智能指针

每个 unique_ptr 对象只能拥有一个指向的对象,不能复制,但可以转移所有权

std::shared_ptr

共享所有权的智能指针

多个 shared_ptr 可以同时指向同一个对象,当最后一个 shared_ptr 被销毁或重置时,才会释放所指向的对象

std::weak_ptr

弱引用智能指针

配合shared_ptr引入的一种智能指针,它不增加引用计数,主要用于解决 shared_ptr 之间的循环引用问题

简述

  • unique_ptr:独占式指针,同一时刻只能有一个指针指向同一个对象
  • shared_ptr:共享式指针,同一时刻可以有多个指针指向同一个对象
  • weak_ptr:用来解决shared_ptr相互引用导致的死锁问题

理解

  1. 智能指针利用了RAII(Resource Acquisition Is Initializatio 资源获取即初始化)
    对普通的指针进行封装,这使得智能指针实质是一个对象,行为表现的却像一个指针
  2. 智能指针防止
    ①忘记调用delete释放内存
    ②程序异常的进入catch块忘记释放内存
    ③多次释放同一个指针(会造成程序崩溃)
  3. 智能指针把值语义转换成引用语义

    

实现原理

1. std::unique_ptr 的实现原理

std::unique_ptr 是最简单的智能指针,它的实现基于 RAII(Resource Acquisition Is Initialization)原则。unique_ptr 在构造时获取资源,在析构时自动释放资源。由于它是独占所有权的,因此不允许复制,但可以通过 std::move 来转移所有权。

2. std::shared_ptr 的实现原理

std::shared_ptr 通过引用计数机制来管理对象的生命周期。多个 shared_ptr 可以共享同一个对象,只有当所有共享该对象的 shared_ptr 都被销毁或重置时,才会释放该对象。

引用计数:shared_ptr 内部维护一个控制块(control block),其中包含两个计数器:

强引用计数:记录有多少个 shared_ptr 正在共享该对象。当强引用计数为 0 时,对象会被销毁。

弱引用计数:记录有多少个 weak_ptr 正在引用该对象。弱引用计数用于管理控制块的生命周期,当弱引用计数也为 0 时,控制块也会被释放。

线程安全:shared_ptr 的引用计数操作是线程安全的,即多个线程可以同时对同一个 shared_ptr 进行增减引用计数,而不会导致竞争条件。

3. std::weak_ptr 的实现原理

std::weak_ptr 是 shared_ptr 的一种弱引用形式,它不增加强引用计数,因此不会影响对象的生命周期。weak_ptr 主要用于解决 shared_ptr 之间的循环引用问题。

弱引用:weak_ptr 不直接持有对象的所有权,它只是通过 shared_ptr 的控制块来访问对象。如果对象已经被销毁,weak_ptr 会感知到这一点,并返回一个空的 shared_ptr。

锁机制:通过 lock() 方法,weak_ptr 可以临时获得一个 shared_ptr,从而安全地访问对象。如果对象已经被销毁,lock() 会返回一个空的 shared_ptr。

代码示例

#include <iostream>
#include <memory>  // 引入智能指针的头文件// 定义一个简单的类
class Resource {
public:Resource() { std::cout << "Resource created\n"; }~Resource() { std::cout << "Resource destroyed\n"; }void doSomething() const {std::cout << "Doing something...\n";}
};int main() {// === 使用 unique_ptr ==={// 创建一个 unique_ptr,独占所有权std::unique_ptr<Resource> uniquePtr = std::make_unique<Resource>();// 调用对象的方法uniquePtr->doSomething();// 尝试复制 unique_ptr(编译错误)// std::unique_ptr<Resource> anotherUniquePtr = uniquePtr;// 移动所有权std::unique_ptr<Resource> movedUniquePtr = std::move(uniquePtr);// uniquePtr 现在为空,无法再访问资源if (!uniquePtr) {std::cout << "uniquePtr is now empty\n";}// movedUniquePtr 仍然持有资源movedUniquePtr->doSomething();}  // 当作用域结束时,movedUniquePtr 自动释放资源std::cout << "After unique_ptr scope\n";// === 使用 shared_ptr ==={// 创建一个 shared_ptr,共享所有权std::shared_ptr<Resource> sharedPtr1 = std::make_shared<Resource>();// 获取引用计数std::cout << "Reference count: " << sharedPtr1.use_count() << "\n";// 创建另一个 shared_ptr,共享同一个对象std::shared_ptr<Resource> sharedPtr2 = sharedPtr1;std::cout << "Reference count after copying: " << sharedPtr1.use_count() << "\n";// 调用对象的方法sharedPtr1->doSomething();// 当 sharedPtr2 超出作用域时,引用计数减1}  // sharedPtr2 超出作用域,引用计数变为1// sharedPtr1 仍然存在,对象不会被销毁std::cout << "After shared_ptr2 scope\n";// === 使用 weak_ptr ==={// 创建一个 shared_ptr,用于创建 weak_ptrstd::shared_ptr<Resource> sharedPtr3 = std::make_shared<Resource>();// 创建一个 weak_ptr,弱引用 sharedPtr3 所指向的对象std::weak_ptr<Resource> weakPtr = sharedPtr3;// 检查 weak_ptr 是否仍然有效if (auto lockedPtr = weakPtr.lock()) {// 如果对象仍然存在,lockedPtr 是一个有效的 shared_ptrstd::cout << "Object is still alive\n";lockedPtr->doSomething();} else {// 对象已被销毁std::cout << "Object has been destroyed\n";}// 释放 sharedPtr3,对象将被销毁sharedPtr3.reset();// 再次检查 weak_ptrif (auto lockedPtr = weakPtr.lock()) {// 对象已被销毁,lockedPtr 为空std::cout << "Object is still alive\n";} else {std::cout << "Object has been destroyed\n";}}return 0;
}

代码输出 

Resource created
Doing something...
uniquePtr is now empty
Doing something...
Resource destroyed
After unique_ptr scope
Resource created
Reference count: 1
Reference count after copying: 2
Doing something...
Resource destroyed
After shared_ptr2 scope
Resource created
Object is still alive
Doing something...
Resource destroyed
Object has been destroyed

        智能指针是C++中非常重要的工具,能够有效管理动态分配的内存,避免常见的内存管理问题。std::unique_ptr 适用于独占所有权的场景,std::shared_ptr 适用于共享所有权的场景,而 std::weak_ptr 则用于解决循环引用问题。

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

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

相关文章

Modbus数据网关在制造企业的应用与效果

Modbus是一种广泛应用于工业通信的协议&#xff0c;支持多种设备间的数据交换&#xff0c;如传感器、仪器仪表、PLC、工业机器人、数控机床等。Modbus数据网关则是一种网络通信转换设备&#xff0c;它能够将Modbus协议的数据转换为其他主流协议&#xff08;如MQTT、OPC UA、HTT…

秒鲨后端之MyBatis【2】默认的类型别名、MyBatis的增删改查、idea中设置文件的配置模板、MyBatis获取参数值的两种方式、特殊SQL的执行

别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01;! ! ! 下篇更新&#xff1a; 秒鲨后端之MyBatis【3】自定义映射resultMap、动态SQL、MyBatis的缓存、MyBatis的逆向工程、分页插件。 默认的类型别名 MyBatis的增删改查 添加 <!--int insertUs…

从数据仓库到数据中台再到数据飞轮:电信行业的数据技术进化史

前言 大家好&#xff0c;我是一名大数据开发工程师&#xff0c;电信行业作为高度数据驱动的行业&#xff0c;长期以来通过技术创新不断优化服务质量和业务运营。从最早期的数据仓库&#xff0c;到数据中台&#xff0c;再到如今的数据飞轮&#xff0c;电信行业的数据技术经历了几…

【机器学习(九)】分类和回归任务-多层感知机(Multilayer Perceptron,MLP)算法-Sentosa_DSML社区版 (1)111

文章目录 一、算法概念111二、算法原理&#xff08;一&#xff09;感知机&#xff08;二&#xff09;多层感知机1、隐藏层2、激活函数sigma函数tanh函数ReLU函数 3、反向传播算法 三、算法优缺点&#xff08;一&#xff09;优点&#xff08;二&#xff09;缺点 四、MLP分类任务…

【NLP高频面题 - 高效微调篇】什么是提示微调?

【NLP高频面题 - 高效微调篇】什么是提示微调&#xff1f; 重要性&#xff1a;★ NLP Github 项目&#xff1a; NLP 项目实践&#xff1a;fasterai/nlp-project-practice 介绍&#xff1a;该仓库围绕着 NLP 任务模型的设计、训练、优化、部署和应用&#xff0c;分享大模型算法…

基于kraft部署kafka集群

kafka介绍 Apache Kafka 是一个开源的分布式事件流平台&#xff0c;被数千家公司用于高性能数据管道、流分析、数据集成和关键任务应用。 Kafka是一个拥有高吞吐、可持久化、可水平扩展&#xff0c;支持流式数据处理等多种特性的分布式消息流处理中间件&#xff0c;采用分布式…

debug diagnostic tool 调试.net的错误

下载安装debug diagnostic tool debug diagnostic tool 设置 因为现在都是多cpu,所以cpu可以设置低一点,就抓去数据 微软教程

京东科技基于 Apache SeaTunnel 复杂场景适配 #数据集成

作者&#xff1a;宁诚、陈伟强 京东科技架构师 技术背景与挑战 技术背景 2023年第一季度&#xff0c;京东科技的营销与数据资产部开始规划数据洞察系统产品&#xff0c;主要服务于京东科技营销体系的业务团队。该系统的分析内容涵盖了京东集团在商城、金融和物流等各个业务系…

基于Spring Boot的工商局商家管理系统

一、系统背景与意义 随着市场经济的不断发展&#xff0c;商家数量日益增多&#xff0c;工商局对商家的管理需求也日益复杂。传统的管理方式存在诸多弊端&#xff0c;如信息不透明、管理效率低下等。因此&#xff0c;开发一种高效、便捷、智能化的工商局商家管理系统显得尤为重…

论文DiffBP: generative diffusion of 3D molecules for target protein binding

研究背景 在药物发现中&#xff0c;生成能与特定蛋白质结合的分子至关重要但极具挑战。以往的工作大多采用自回归方式逐个生成原子的元素类型和三维坐标&#xff0c;但在真实分子系统中&#xff0c;原子间的相互作用是全局性的&#xff0c;基于能量考虑&#xff0c;概率建模应基…

如何在谷歌浏览器中进行网络速度测试

在当今高度依赖互联网的时代&#xff0c;网络速度的快慢直接影响着我们的工作、学习和娱乐等各个方面。因此&#xff0c;了解如何准确测试网络速度成为了每个网民应掌握的基本技能。谷歌浏览器作为一款广泛使用的浏览器&#xff0c;提供了便捷且高效的网络速度测试功能。本文将…

JAVAweb学习日记(三)Ajax

一、Ajax Axios&#xff1a; 入门&#xff1a; 案例&#xff1a; 二、前后端分离开发 介绍&#xff1a; APIfox&#xff1a; Apifox 前端工程化&#xff1a; 环境准备&#xff1a; Vue项目-创建&#xff1a; Vue项目-配置端口&#xff1a; Vue项目-开发流程&#xff1a; Vue…

聊天社交管理系统 Java 源码,构建个性化社交空间

社交网络已经是我们生活中非常重要的一部分&#xff0c;一个高效、个性化的聊天社交管理系统都能极大提升用户体验。 多种消息通知类型&#xff0c;支持新消息通知&#xff0c;图标闪烁、声音提醒和弹窗提醒。 1.音视频&#xff1a; 支持二人聊天&#xff0c;有语音聊天、桌面…

Shion(时间追踪工具) v0.13.2

Shion 是一款多功能的时间追踪软件&#xff0c;旨在帮助用户更好地管理时间。它提供了多种自定义数据卡片&#xff0c;如github风格的一年概览、30天单项数据柱状图和每日24小时活动展示&#xff0c;以便用户清晰地了解自己的日常生活。Shion还具备自动监听程序使用时间的功能&…

USDZ格式轻松转OBJ

USDZ格式简介 USDZ&#xff0c;作为苹果公司与PIXAR工作室联手推出的新型AR文件格式&#xff0c;正逐步成为增强现实&#xff08;AR&#xff09;领域中的佼佼者。USDZ文件不仅支持丰富的3D模型数据&#xff0c;还能嵌入材质、动画及交互信息&#xff0c;为用户带来沉浸式的AR体…

100V宽压输入反激隔离电源,适用于N道沟MOSFET或GaN或5V栅极驱动器,无需光耦合

说明: PC4411是一个隔离的反激式控制器在宽输入电压下具有高效率范围为2.7V至100V。它直接测量初级侧反激输出电压波形&#xff0c;不需要光耦合器或第三方用于调节的绕组。设置输出只需要一个电阻器电压。PC4411提供5V栅极驱动驱动外部N沟道MOSFET的电压或GaN。内部补偿和软启…

Linux的启动流程

目录 1、 加电开机&#xff0c;启动BIOS进行自检。 2、读取MBR(Master Boot Record, 主要启动记录区)。 3、加载GRUB&#xff08;GRand Unified Bootloader&#xff09;菜单。 4、加载内核&#xff08;kernel&#xff09;和驱动程序 5、运行systemd进程&#xff0c;加载如…

打造高效的 LaTeX 公式编辑器

在科研和工程领域&#xff0c;LaTeX 是最常用的公式排版工具之一。为了帮助用户更加高效地编辑和管理 LaTeX 公式&#xff0c;我们开发了一个集成了实时预览、公式管理和多格式导出功能的公式编辑器。本文将介绍这个工具的核心功能&#xff0c;并展示部分实现代码。 核心功能 …

OpenAI 12天发布会:AI革命的里程碑@附35页PDF文件下载

在人工智能的浪潮中&#xff0c;OpenAI的12天发布会无疑是2024年科技界的一场盛宴。从12月5日开始&#xff0c;OpenAI连续12天每天发布一个新应用或功能&#xff0c;标志着AI技术的又一次飞跃。本文将梳理这些激动人心的发布&#xff0c;带你一探究竟。 OpenAI发布会概览 Ope…

水电站视频智能监控系统方案设计与技术应用方案

一、背景需求 水电站作为国家重要的能源基地&#xff0c;其安全运行对于保障能源供应和社会稳定具有重要意义。然而&#xff0c;传统的人工监控方式存在着诸多问题&#xff0c;如人力成本高、监控范围有限、反应不及时等。因此&#xff0c;水电站急需引进一种先进的视频智能监控…