C++ 智能指针 unique_ptr shared_ptr weak_ptr小练习

智能指针是 C++11 引入的一项重要特性,它可以帮助我们管理动态分配的内存,自动释放内存,避免内存泄漏和悬空指针的问题。智能指针有三种常用类型:std::unique_ptrstd::shared_ptrstd::weak_ptr

为了帮助你熟悉智能指针的使用,下面是一些练习题,涵盖了智能指针的基本用法以及一些常见的应用场景。

练习 1:使用 std::unique_ptr

任务:创建一个 std::unique_ptr,用于管理一个动态分配的 int 类型的内存,并打印其值。

#include <iostream>
#include <memory>int main() {// 创建一个unique_ptr来管理动态分配的内存// 请补充代码,使用 std::make_unique 创建一个 unique_ptrreturn 0;
}

提示:使用 std::make_unique 来创建 std::unique_ptr,并访问其管理的对象。


练习 2:std::unique_ptr 的转移所有权

任务:展示如何通过 std::move 转移 std::unique_ptr 的所有权。

#include <iostream>
#include <memory>void print_value(std::unique_ptr<int> ptr) {std::cout << "Value: " << *ptr << std::endl;
}int main() {std::unique_ptr<int> ptr1 = std::make_unique<int>(10);// 转移所有权到 ptr2std::unique_ptr<int> ptr2 = std::move(ptr1);// 确保 ptr1 已经不再拥有资源,尝试解引用 ptr1 会导致错误if (ptr1 == nullptr) {std::cout << "ptr1 is now null." << std::endl;}// 打印 ptr2 中的值print_value(std::move(ptr2));return 0;
}

提示:使用 std::move 来转移 std::unique_ptr 的所有权。转移后,ptr1 会变为空指针,无法再访问其管理的资源。


练习 3:使用 std::shared_ptr

任务:使用 std::shared_ptr 来管理一个动态分配的 int 类型的内存,并展示多个 shared_ptr 指向同一内存时,引用计数的变化。

#include <iostream>
#include <memory>int main() {std::shared_ptr<int> ptr1 = std::make_shared<int>(20);// 创建 ptr2,并共享 ptr1 管理的内存std::shared_ptr<int> ptr2 = ptr1;std::cout << "ptr1's value: " << *ptr1 << std::endl;std::cout << "ptr2's value: " << *ptr2 << std::endl;// 输出引用计数std::cout << "Reference count: " << ptr1.use_count() << std::endl;return 0;
}

提示std::shared_ptr 允许多个指针共享同一块内存,它会自动管理引用计数。当引用计数为 0 时,内存会自动释放。


练习 4:std::shared_ptr 的循环引用问题

任务:通过一个简单的类和 std::shared_ptr,模拟一个循环引用的情况,并展示为什么会导致内存泄漏。

#include <iostream>
#include <memory>class A;
class B;class A {
public:std::shared_ptr<B> b;~A() { std::cout << "A destroyed!" << std::endl; }
};class B {
public:std::shared_ptr<A> a;~B() { std::cout << "B destroyed!" << std::endl; }
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b = b;b->a = a;// 在这里,a 和 b 的引用计数会永远不为 0,导致内存无法释放return 0;
}

提示:循环引用导致两个 shared_ptr 永远无法释放内存,因为它们互相引用,引用计数始终大于 0。可以通过使用 std::weak_ptr 来解决这个问题。


练习 5:使用 std::weak_ptr 打破循环引用

任务:修改上一题的代码,使用 std::weak_ptr 来解决循环引用的问题。

#include <iostream>
#include <memory>class A;
class B;class A {
public:std::shared_ptr<B> b;~A() { std::cout << "A destroyed!" << std::endl; }
};class B {
public:std::weak_ptr<A> a;  // 使用 weak_ptr 打破循环引用~B() { std::cout << "B destroyed!" << std::endl; }
};int main() {std::shared_ptr<A> a = std::make_shared<A>();std::shared_ptr<B> b = std::make_shared<B>();a->b = b;b->a = a;  // 使用 weak_ptr 避免循环引用return 0;
}

提示:使用 std::weak_ptr 来避免循环引用问题,weak_ptr 不增加引用计数,因此不会导致资源无法释放。


练习 6:std::shared_ptr 和自定义删除器

任务:使用 std::shared_ptr 创建一个自定义删除器,删除时打印一条消息。

#include <iostream>
#include <memory>void custom_deleter(int* ptr) {std::cout << "Deleting pointer: " << ptr << std::endl;delete ptr;
}int main() {// 创建 shared_ptr 时传入自定义删除器std::shared_ptr<int> ptr = std::shared_ptr<int>(new int(10), custom_deleter);std::cout << "Value: " << *ptr << std::endl;return 0;
}

提示std::shared_ptr 允许传入自定义的删除器,用来控制资源的释放方式。在删除 shared_ptr 时,删除器会被调用。


练习 7:std::unique_ptr 和数组

任务:使用 std::unique_ptr 来管理动态分配的数组。

#include <iostream>
#include <memory>int main() {// 创建一个unique_ptr来管理动态分配的数组std::unique_ptr<int[]> arr = std::make_unique<int[]>(5);// 给数组赋值并打印for (int i = 0; i < 5; ++i) {arr[i] = i * 10;}for (int i = 0; i < 5; ++i) {std::cout << arr[i] << " ";}return 0;
}

提示std::unique_ptr 可以用于管理数组,创建时使用 std::make_unique<T[]> 来分配动态数组。


练习 8:std::shared_ptr 与自定义类型

任务:创建一个自定义类并使用 std::shared_ptr 来管理它的实例。

#include <iostream>
#include <memory>class MyClass {
public:MyClass() { std::cout << "MyClass Constructor" << std::endl; }~MyClass() { std::cout << "MyClass Destructor" << std::endl; }
};int main() {std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();std::cout << "Shared pointer in scope" << std::endl;return 0;
}

提示std::shared_ptr 可以用于管理自定义类型的对象。使用 std::make_shared 创建并管理对象实例。


这些练习将帮助你理解和掌握 C++ 中智能指针的使用,特别是 std::unique_ptrstd::shared_ptr 的基本概念、引用计数、资源管理,以及如何避免常见的内存管理问题(如循环引用)。

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

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

相关文章

Java 大视界 -- Java 大数据未来十年的技术蓝图与发展愿景(95)

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

【网络安全 | 漏洞挖掘】账户接管+PII+原漏洞绕过

文章目录 前言正文前言 本文涉及的所有漏洞测试共耗时约三周,成果如下: 访问管理面板,成功接管目标列出的3000多家公司。 获取所有员工的真实指纹、机密文件及个人身份信息(PII)。 绕过KYC认证,成功接管电话号码。 绕过此前发现的漏洞。 正文 在测试目标时,我发现了一…

MySQL的Union和OR查询

这里写目录标题 **1. 创建表和索引****2. 编写 UNION 查询****3. 使用 EXPLAIN 分析查询****4. 分析 EXPLAIN 结果****可能的结果分析**&#xff1a; **5. 验证索引合并****总结****1. UNION 操作的分析****为什么使用临时表&#xff1f;** 2. OR 条件的分析为什么使用索引合并…

二叉排序树 -- AVL树 红黑树

手撕 – AVL树、红黑树 个人主页&#xff1a;顾漂亮 文章专栏&#xff1a;Java数据结构 文章目录 手撕 -- AVL树、红黑树1.AVL树1.1AVL树的概念1.2AVL树的性质1.3AVL树的实现 -- Java代码1.4AVL树的性能分析 2.红黑树2.1概念2.2红黑树的性质2.3红黑树的实现2.4AVL树和红黑树的比…

在 .NET 8/9 中使用 AppUser 进行 JWT 令牌身份验证

文章目录 一、引言二、什么是 JSON Web 令牌&#xff1f;三、什么是 JSON Web 令牌结构&#xff1f;四、设置 JWT 令牌身份验证4.1 创建新的 .NET 8 Web API 项目4.2 安装所需的 NuGet 软件包4.3 创建 JWT 配置模型4.4 将 JWT 配置添加到您的 appsettings.json 中4.5 为 Config…

问卷数据分析|SPSS实操之相关分析

皮尔逊还是斯皮尔曼的选取主要看数据的分布 当数据满足正态分布且具有线性关系时&#xff0c;用皮尔逊相关系数 当有一个不满住时&#xff0c;用斯皮尔曼相关系数 1. 选择分析--相关--双变量 2. 将Z1-Y2加入到变量中&#xff0c;选择皮尔逊 3. 此处为结果&#xff0c;可看我案…

自动化办公|xlwings生成图表

在日常的数据分析和报告生成中&#xff0c;Excel图表是一个非常重要的工具。它能够帮助我们直观地展示数据&#xff0c;发现数据中的规律和趋势。然而&#xff0c;手动创建和调整图表往往耗时且容易出错。幸运的是&#xff0c;借助Python的xlwings库&#xff0c;我们可以自动化…

Javascript使用Sodium库实现 aead_xchacha20poly1305_ietf加密解密,以及与后端的密文交互

Node.js环境安装 sodium-native (其他库可能会出现加密解密失败&#xff0c;如果要使用不一样的库&#xff0c;请自行验证) npm install sodium-native 示例代码&#xff0c;使用的是 sodium-native v4.3.2 (其他版本可能会有变化&#xff0c;如果要使用&#xff0c;请自行验…

【Linux】匿名管道的应用场景-----管道进程池

目录 一、池化技术 二、简易进程池的实现&#xff1a; Makefile task.h task.cpp Initchannel函数&#xff1a; 创建任务&#xff1a; 控制子进程&#xff1a; 子进程执行任务&#xff1a; 清理收尾&#xff1a; 三、全部代码&#xff1a; 前言&#xff1a; 对于管…

使用LangChain构建第一个ReAct Agent

使用LangChain构建第一个ReAct Agent 准备环境 使用Anaconda 安装python 3.10 安装langchain、langchain_openai、langchain_community &#xff08;安装命令 pip install XXX&#xff09; 申请DeepSeek API&#xff1a;https://platform.deepseek.com/api_keys&#xff08;也…

多人协同创作gitea

多人协同创作gitea 在多台设备上协同使用Gitea&#xff0c;主要是通过网络访问Gitea服务器上的仓库来进行代码管理和协作。以下是一些关键步骤和建议&#xff0c;帮助你在多台设备上高效地使用Gitea进行协作&#xff1a; 1. 确保Gitea服务可访问 首先&#xff0c;你需要确保…

【个人开源】——从零开始在高通手机上部署sd(二)

代码&#xff1a;https://github.com/chenjun2hao/qualcomm.ai 推理耗时统计 单位/ms 硬件qnncpu_clipqnncpu_unetqnncpu_vaehtp_cliphtp_unethtp_vae骁龙8 gen124716.994133440.39723.215411.097696.327 1. 下载依赖 下载opencv_x64.tar,提取码: rrbp下载opencv_aarch64.t…

SpringCloud系列教程:微服务的未来(二十五)-基于注解的声明队列交换机、消息转换器、业务改造

前言 在现代分布式系统中&#xff0c;消息队列是实现服务解耦和异步处理的关键组件。Spring框架提供了强大的支持&#xff0c;使得与消息队列&#xff08;如RabbitMQ、Kafka等&#xff09;的集成变得更加便捷和灵活。本文将深入探讨如何利用Spring的注解驱动方式来配置和管理队…

学习经验分享【39】YOLOv12——2025 年 2 月 19 日发布的以注意力为核心的实时目标检测器

YOLO算法更新速度很快&#xff0c;已经出到V12版本&#xff0c;后续大家有想发论文或者搞项目可更新自己的baseline了。 代码&#xff1a;GitHub - sunsmarterjie/yolov12: YOLOv12: Attention-Centric Real-Time Object Detectors 摘要&#xff1a;长期以来&#xff0c;增强 …

Pytorch实现之特征损失与残差结构稳定GAN训练,并训练自己的数据集

简介 简介:生成器和鉴别器分别采用了4个新颖设计的残差结构实现,同时在损失中结合了鉴别器层的特征损失来提高模型性能。 论文题目:Image Generation by Residual Block Based Generative Adversarial Networks(基于残留块的生成对抗网络产生图像) 会议:2022 IEEE Int…

后“智驾平权”时代,谁为安全冗余和体验升级“买单”

线控底盘&#xff0c;正在成为新势力争夺下一个技术普及红利的新赛点。 尤其是进入2025年&#xff0c;比亚迪、长安等一线传统自主品牌率先开启高阶智驾的普及战&#xff0c;加上此前已经普及的智能座舱&#xff0c;舱驾智能的「科技平权」进一步加速行业启动「线控底盘」上车窗…

【Node.js】express框架

目录 1初识express框架 2 初步使用 2.1 安装 2.2 创建基本的Web服务器 2.3 监听方法 2.3.1 监听get请求 2.3.2 监听post请求 2.4 响应客户端 2.5 获取url中的参数(get) 2.5.1 获取查询参数 2.5.2 获取动态参数 2.6 托管静态资源 2.6.1 挂载路径前缀 2.6.2 托管多…

树形DP(树形背包+换根DP)

树形DP 没有上司的舞会 家常便饭了&#xff0c;写了好几遍&#xff0c;没啥好说的&#xff0c;正常独立集问题。 int head[B]; int cnt; struct node {int v,nxt; }e[B<<1]; void modify(int u,int v) {e[cnt].nxthead[u];e[cnt].vv;head[u]cnt; } int a[B]; int f[B]…

REACT--组件通信

组件之间如何进行通信&#xff1f; 组件通信 组件的通信主要借助props传递值 分为整体接收、解构接收 整体接收 import PropTypes from prop-types;//子组件 function Welcome(props){return (<div>hello Welcome,{props.count},{props.msg}</div>) }// 对 We…

【排序算法】六大比较类排序算法——插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序【详解】

文章目录 六大比较类排序算法&#xff08;插入排序、选择排序、冒泡排序、希尔排序、快速排序、归并排序&#xff09;前言1. 插入排序算法描述代码示例算法分析 2. 选择排序算法描述优化代码示例算法分析 3. 冒泡排序算法描述代码示例算法分析与插入排序对比 4. 希尔排序算法描…