C++学习第二十八课:C++ 中的智能指针详解

在这里插入图片描述

在 C++ 中,内存管理是每个程序员都需要面对的问题。在处理动态分配的内存时,如果忘记释放内存,可能会导致内存泄漏。为了解决这个问题,C++11 引入了智能指针的概念。本文将详细介绍 C++ 中使用智能指针的方法,并结合实际案例进行讲解。

一、什么是智能指针

智能指针是一种对象,它可以像常规指针一样使用,但具有自动管理内存的功能。当智能指针离开其作用域时,它会自动删除所指向的对象,从而避免内存泄漏。C++11 提供了两种智能指针:std::unique_ptrstd::shared_ptr

二、std::unique_ptr 详解

std::unique_ptr 是一种独占所有权的智能指针,即同一时间只能有一个 std::unique_ptr 指向一个对象。当 std::unique_ptr 被销毁时,它会自动删除所指向的对象。

示例代码:

#include <iostream>
#include <memory>class Test {
public:Test() { std::cout << "Test 构造函数" << std::endl; }~Test() { std::cout << "Test 析构函数" << std::endl; }
};int main() {std::unique_ptr<Test> ptr(new Test());// 当 ptr 离开作用域时,自动调用 Test 的析构函数return 0;
}

输出结果:

Test 构造函数
Test 析构函数

三、std::shared_ptr 详解

std::shared_ptr 是一种共享所有权的智能指针,即可以有多个 std::shared_ptr 指向同一个对象。当最后一个 std::shared_ptr 被销毁时,它会自动删除所指向的对象。

示例代码:

#include <iostream>
#include <memory>class Test {
public:Test() { std::cout << "Test 构造函数" << std::endl; }~Test() { std::cout << "Test 析构函数" << std::endl; }
};int main() {{std::shared_ptr<Test> ptr1(new Test());std::shared_ptr<Test> ptr2 = ptr1;// 当 ptr1 和 ptr2 离开作用域时,自动调用 Test 的析构函数}return 0;
}

输出结果:

Test 构造函数
Test 析构函数

四、std::make_uniquestd::make_shared

为了更方便地创建智能指针,C++11 提供了 std::make_uniquestd::make_shared 函数。这两个函数可以简化智能指针的创建过程,并提高代码的可读性。

示例代码:

#include <iostream>
#include <memory>class Test {
public:Test() { std::cout << "Test 构造函数" << std::endl; }~Test() { std::cout << "Test 析构函数" << std::endl; }
};int main() {// 使用 std::make_unique 创建 unique_ptrstd::unique_ptr<Test> ptr1 = std::make_unique<Test>();// 使用 std::make_shared 创建 shared_ptrstd::shared_ptr<Test> ptr2 = std::make_shared<Test>();return 0;
}

输出结果:

Test 构造函数
Test 构造函数

五、智能指针的使用注意事项

  1. 不要使用 delete 操作符删除智能指针所指向的对象,这会导致双重释放问题。
  2. 不要将原始指针(raw pointer)和智能指针混用,这可能导致内存泄漏或双重释放问题。
  3. 不要将两个 std::unique_ptr 赋值给同一个对象,这会导致所有权冲突。
  4. 不要将 std::unique_ptr 转换为 std::shared_ptr,这可能导致循环引用问题。

智能指针是C++中用于自动管理对象生命周期的工具,它们通过引用计数或其他机制来确保在不再需要时自动释放对象。以下是对智能指针类型的细致讲解:

  1. 深复制(Deep Copy)
  • 深复制是指在复制对象时,不仅复制对象的值,还复制对象所指向的内存内容。
  • 对于智能指针而言,深复制意味着创建一个新的动态分配的对象,并将原对象的内容复制到新对象中,然后让智能指针管理这个新的对象。
  • std::shared_ptrstd::unique_ptr 都支持深复制,因为它们都会创建一个新的动态分配的对象。
  1. 写时复制(Copy-on-Write, CoW)
  • 写时复制是一种优化策略,当多个智能指针共享同一个对象时,只有在其中一个智能指针试图修改对象时,才会进行实际的复制操作。
  • std::shared_ptr 使用写时复制机制来提高效率,在没有写入操作时,多个 shared_ptr 可以安全地共享同一个对象。
  1. 引用计数智能指针(Reference Counting Smart Pointers)
  • 引用计数智能指针通过维护一个引用计数来跟踪有多少个智能指针指向同一个对象。
  • std::shared_ptr 是一个引用计数智能指针,当最后一个 shared_ptr 被销毁时,它会自动释放所管理的对象。
  1. 引用链接智能指针(Reference Linking Smart Pointers)
  • 引用链接智能指针通常不直接管理对象的生命周期,而是通过观察其他智能指针来间接实现。
  • std::weak_ptr 是一种引用链接智能指针,它提供了一种方式来避免潜在的循环引用问题,但不会增加对象的引用计数。
  1. 破坏性复制(Disastrous Copy)
  • 破坏性复制并不是智能指针的一个标准概念,但可以理解为在复制过程中可能导致意外行为的情况。
  • 例如,当一个 shared_ptr 管理的资源被另一个 shared_ptr 或原始指针释放时,可能会导致悬挂指针或重复释放资源的问题。

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

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

相关文章

并查集刷题笔记

leetcode-1971:寻找图中是否存在路径 并查集可以解决的问题是&#xff1a;判断两个点是否在同一个集合之中 并查集模版&#xff1a; 最重要的两部&#xff1a;将两点连接以及对某一节点寻根。 一、初始化&#xff1a;{init()} 将每个节点的父节点初始化为自身。 二、寻根…

nvm安装踩雷 报错‘node‘ 不是内部或外部命令

需要排查以下内容&#xff1a; 1.nvm install node版本号后使用nvm use node版本号进行应用 2.在安装nvm前&#xff0c;确保电脑上不存在之前安装过的node的相关信息&#xff0c;包括环境变量、之前安装的nodejs、node_global文件夹&#xff08;存储全局安装的 Node.js 模块和…

永倍达 最新消息!发放消费券! 重新开网?

大家好 我是一家软件开发公司的产品经理 吴军 我又又又又又叕来蹭热度了&#xff0c;最近永倍达有新动作&#xff01;发放消费券&#xff1f; 店长群最新通知 4.15号开始发放消费券 一个月之后才可以重新提现 今天是5.10号离5.18也不远了 大家拭目以待看看到底能不能提现&a…

“紧急联系人功能”的智慧守护

在当今科技融入生活的每一个角落&#xff0c;一款名为“蝙蝠避障”专为盲人设计的辅助应用正悄然改变着视障群体的日常出行体验。这款应用中&#xff0c;一个看似不起眼却至关重要的功能——“紧急联系人功能”&#xff0c;以其强大的实用性和人文关怀&#xff0c;成为了盲人朋…

一套3D PACS系统源码:可实现医学影像获取、存档、观片、处理、打印多项应用、基于C#+VC + MSSQL开发的全套PACS源码

一套3D PACS系统源码&#xff1a;可实现医学影像获取、存档、观片、处理、打印多项应用 PACS的功能价值在于通过连接不同的影像设备&#xff0c;存储与管理图像&#xff0c;图像的调用与后处理&#xff0c;实现资源共享&#xff0c;降低成本&#xff0c;达到提高工作效率、提升…

Mysql之SQL Mode问题

Mysql SQL Mode问题简谈 1. Mysql SQL Mode简介2. 常用的SQL Mode3. SQL Mode在迁移中的应用 1. Mysql SQL Mode简介 SQL Mode定义了Mysql应支持的SQL语句、数据校验等&#xff0c;这样可以容易在不同的环境中使用Mysql。 通过设置SQL Mode&#xff0c;可以完成不同严格程度的数…

halcon学习之一维测量基础

目录 创建测量矩形&#xff0c;获取测量句柄 gen_measure_rectangle2&#xff08;&#xff09; 使用句柄进行测量 measure_pos&#xff08;&#xff09; 修改参数Threshold 修改参数Transition 修改参数select 参数RowEdge&#xff0c;ColumnEdge&#xff0c;Distance …

4步快速配置Java、MySQL、Maven环境(windows)

每次入职一家新公司或者用一台其他的临时电脑或者新电脑时都要重新配置Java开发环境&#xff0c;很麻烦&#xff0c;因此我在这里记录一下快速配置环境的方式&#xff0c;四步搞定&#xff01;此处以win为操作系统进行讲解。 第一步&#xff1a;下载链接 下载链接&#xff1a…

Calico 和 Flannel 区别,以及各自优缺点

Calico 和 Flannel 都是 Kubernetes 中常用的网络插件&#xff0c;用于在集群中提供网络通信功能&#xff0c;但它们有一些区别和各自的优缺点。 Calico&#xff1a; 特点&#xff1a; 基于BGP协议&#xff1a;Calico 使用BGP协议来实现路由&#xff0c;每个节点上的容器都有一…

【JavaWeb】网上蛋糕商城后台-商品管理

概念 本文讲解和实现网上蛋糕商城的后台管理系统中的商品管理功能。 商品列表 点击后台管理系统的head.jsp头部的“商品管理”功能选项&#xff0c;向服务器发送请求/admin/goods_list 因此需要在servlet包中创建AdminGoodsListServlet类&#xff0c;用于获取商品信息列表 …

linux 基础命令使用

命令 su 用于切换到另一个用户身份&#xff0c;通常是超级用户(root)。su命令可以用来在命令行下切换用户&#xff0c;也可以在脚本中使用。 语法&#xff1a; su [选项] [用户名] 选项&#xff1a; - -c&#xff1a;执行完命令后&#xff0c;立即退出su命令&#xff1b;…

zblog中用户中心-邀请码注册插件的导出功能补充

自己加了一个导出未使用的邀请码功能&#xff0c;可惜我不是入驻作者&#xff0c;没有权限发布&#xff0c;之前被一条大河拒了&#xff0c;他说我抄他代码&#xff0c;不给我过审还冷嘲热讽&#xff0c;我一气之下&#xff0c;就没继续申请了&#xff0c;话说我是专业搞java开…

使用JavaScript日历小部件和DHTMLX Gantt的应用场景(二)

DHTMLX Suite UI 组件库允许您更快地构建跨平台、跨浏览器 Web 和移动应用程序。它包括一组丰富的即用式 HTML5 组件&#xff0c;这些组件可以轻松组合到单个应用程序界面中。 DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足项目管理应用…

HTML【安装HBuilder、常用标签】--学习JavaEE的day44

day44 JavaEE 学习过程&#xff1a;前端—>数据库—>服务器端 前端的VUE在框架阶段学习 JavaEE学习过程图 HTML 前端&#xff1a;展示页面、与用户交互 — HTML 后端&#xff1a;数据的交互和传递 — JavaEE/JavaWeb 1. 前端开发的工作模式 开发输出htmlcssjs 理解&am…

PHP的XML格式和AJAX

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;PHP &#x1f4da;参考教程&#xff1a;菜鸟\编程网❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、PHP的XML格式 PHP XML Expat 解析器 XML 是什么…

lora体验

项目链接 GitHub - cloneofsimo/lora: Using Low-rank adaptation to quickly fine-tune diffusion models. 现在如果想体验stable diffusion的lora功能&#xff0c;有很多种渠道吧&#xff0c;虽然lora是微软开源&#xff0c;但是cloneofsimo提供了适配stable diffusion的lor…

Springboot+Vue项目-基于Java+MySQL的车辆管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

STM32(六):定时器PWM呼吸灯 (标准库函数)

前言 上一篇文章已经介绍了如何用STM32单片机中的TIMER定时器来控制LED灯的交替闪烁&#xff0c;实现了点灯的第五种方式。这篇文章我们来介绍一下如何用STM32单片机中的定时器的PWM波来实现LED的“呼吸”。 一、实验原理 关于定时器这边就不多加赘述&#xff0c;详细请看上…

6. path路径绘制:使用path绘制弧线

在可缩放矢量图形&#xff08;SVG&#xff09;中&#xff0c;path 元素是用于绘制各种形状的强大工具&#xff0c;其中包括弧线的绘制。理解弧线绘制的原理对于精确控制图形的形状至关重要。 绘制原理 当指定了这些参数后&#xff0c;浏览器会根据数学公式计算出弧线的路径。…

综合能力 | 误差 | 学习笔记

误差指真值与观测值的差值。 误差分为系统误差&#xff08;消除方法&#xff1a;观测方法、仪器校正、修正等&#xff09;、偶然误差&#xff08;符合正态分布规律&#xff0c;进行计算纠正&#xff09;、粗差&#xff08;一般舍弃&#xff09;。 中误差&#xff08;均方差或标…