C++ 智能指针 unique_ptr shared_ptr weak_ptr小练习
智能指针是 C++11 引入的一项重要特性,它可以帮助我们管理动态分配的内存,自动释放内存,避免内存泄漏和悬空指针的问题。智能指针有三种常用类型:std::unique_ptr、std::shared_ptr 和 std::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_ptr 和 std::shared_ptr 的基本概念、引用计数、资源管理,以及如何避免常见的内存管理问题(如循环引用)。
相关文章:
C++ 智能指针 unique_ptr shared_ptr weak_ptr小练习
智能指针是 C11 引入的一项重要特性,它可以帮助我们管理动态分配的内存,自动释放内存,避免内存泄漏和悬空指针的问题。智能指针有三种常用类型:std::unique_ptr、std::shared_ptr 和 std::weak_ptr。 为了帮助你熟悉智能指针的使…...
Netstat(Network Statistics)网络工具介绍
Netstat 工具详细介绍及常见指令应用 Netstat(Network Statistics)是一个常用的命令行工具,用于显示网络连接、路由表、接口统计信息、伪装连接等信息。它可以帮助用户监控计算机的网络状态,尤其在诊断网络问题时非常有用。Netst…...
内容中台架构下智能推荐系统的算法优化与分发策略
内容概要 在数字化内容生态中,智能推荐系统作为内容中台的核心引擎,承担着用户需求与内容资源精准匹配的关键任务。其算法架构的优化路径围绕动态特征建模与多模态数据融合展开,通过深度强化学习技术实现用户行为特征的实时捕捉与动态更新&a…...
React 高阶组件的优缺点
React 高阶组件的优缺点 优点 1. 代码复用性高 公共逻辑封装:当多个组件需要实现相同的功能或逻辑时,高阶组件可以将这些逻辑封装起来,避免代码重复。例如,多个组件都需要在挂载时进行数据获取操作,就可以创建一个数…...
最新版IDEA下载安装教程
一、下载IDEA 点击前往官网下载 或者去网盘下载 点击前往百度网盘下载 点击前往夸克网盘下载 进去后点击IDEA 然后点击Download 选择自己电脑对应的系统 点击下载 等待下载即可 二、安装IDEA 下载好后双击应用程序 点击下一步 选择好安装目录后点击下一步 勾选这两项后点击…...
DeepSeek最新开源动态:核心技术公布
2月21日午间,DeepSeek在社交平台X发文称,从下周开始,他们将开源5个代码库,以完全透明的方式与全球开发者社区分享他们的研究进展。并将这一计划定义为“Open Source Week”。 DeepSeek表示,即将开源的代码库是他们在线…...
《炒股养家心法.pdf》 kimi总结
《炒股养家心法.pdf》这篇文章详细阐述了一位超级游资炒股养家的心得与技巧,展示了其从40万到10亿的股市传奇。以下是文章中炒股技巧和心得的详细总结: 1.核心理念 市场情绪的理解:炒股养家强调,股市的本质是群体博弈,…...
运维脚本——8.证书自动化管理
场景:自动化SSL/TLS证书的申请、续期和部署,避免证书过期导致服务中断。 示例:使用Shell脚本配合Lets Encrypt的Certbot工具自动续期证书。 #!/bin/bash # 自动续期Lets Encrypt证书并重启服务 certbot renew --quiet --post-hook "syst…...
RDMA ibverbs_API功能说明
设备管理 获取当前活动网卡 返回当前rdma设备列表 struct ibv_device **ibv_get_device_list(int *num_devices);//使用 struct ibv_device **dev_list ibv_get_device_list(NULL);获取网卡名 返回网卡名字字符串:如"mlx5_0",一般通过网卡…...
第15届 蓝桥杯 C++编程青少组中/高级选拔赛 202401 真题答案及解析
第 1 题 【 单选题 】 表达式117 % 16 的结果是( )。 A:0 B:5 C:7 D:10 解析: % 是取模运算符,用于计算两个数相除后的余数。 计算 117 / 16,结果是 7,余数是 5。因此,117 % 16 = 5。答案: B 第 2 题 【 单选题 】 下列选项中,字符数组定义正确的是( …...
【R语言】绘图
一、散点图 散点图也叫X-Y图,它将所有的数据以点的形式展现在坐标系上,用来显示变量之间的相互影响程度。 ggplot2包中用来绘制散点图的函数是geom_point(),但在绘制前需要先用ggplot()函数指定数据集和变量。 下面用mtcars数据集做演示&a…...
Linux基本指令(三)+ 权限
文章目录 基本指令grep打包和压缩zip/unzipLinux和windows压缩包互传tar(重要)Linux和Linux压缩包互传 bcuname -r常用的热键关机外壳程序 知识点打包和压缩 Linux中的权限用户权限 基本指令 grep 1. grep可以过滤文本行 done用于标记循环的结束&#x…...
容器化部署tomcat
容器化部署tomcat 需求在docker容器中部署tomcat,并通过外部机器访问tomcat部署的项目 容器化部署要先装好docker容器(docker安装配置) 实现步骤: 拉取tomcat docker pull tomcat用于列出本地Docker主机上存储的所有镜像 docker images在root目录里面创建tomc…...
vscode软件中引入vant组件
一、vant简介 Vant 是一个轻量、可靠的移动端组件库,于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 官网:介绍 - Vant Weapp 里面的快速上手的教程&a…...
DeepSeek vs ChatGPT:AI 领域的华山论剑,谁主沉浮?
一、引言 在当今科技飞速发展的时代,人工智能(AI)已然成为推动各领域变革的核心力量。而在人工智能的众多分支中,自然语言处理(NLP)因其与人类日常交流和信息处理的紧密联系,成为了最受瞩目的领…...
Ubuntu 22.04 Install deepseek
前言 deepseekAI助手。它具有聊天机器人功能,可以与用户进行自然语言交互,回答问题、提供建议和帮助解决问题。DeepSeek 的特点包括: 强大的语言理解能力:能够理解和生成自然语言,与用户进行流畅的对话。多领域知识&…...
如何将公钥正确添加到服务器的 authorized_keys 文件中以实现免密码 SSH 登录
1. 下载密钥文件 2. RSA 解析 将 id_ed25519 类型的私钥转换为 RSA 类型,要将 ED25519 私钥转换为 RSA 私钥,需要重新生成一个新的 RSA 密钥对。 步骤: 生成新的 RSA 密钥对 使用 ssh-keygen 来生成一个新的 RSA 密钥对。比如,执…...
深入理解设计模式之解释器模式
深入理解设计模式之解释器模式 在软件开发的复杂世界中,我们常常会遇到需要处理特定领域语言的情况。比如在开发一个计算器程序时,需要解析和计算数学表达式;在实现正则表达式功能时,要解析用户输入的正则表达式来匹配文本。这些场景都涉及到对特定语言的解释和执行,而解…...
【WebGL】attribute方式实例化绘制
背景 一般有attribute和uniform两种方式进行实例化绘制 attribute方式实例化 这里需要注意 bufferData和bufferSubData方式的用法顺序和参数 gl.bufferData(target, sizeOrData, usage); sizeOrData(实例化配合bufferSubData 更新数据一般使用这种先)…...
线代[8]|北大丘维声教授《怎样学习线性代数?》(红色字体为博主注释)
文章目录 说明一、线性代数的内容简介二、学习线性代数的用处三、线性代数的特点四、学习线性代数的方法五、更新时间记录 说明 文章中红色字体为博主敲录完丘教授这篇文章后所加,刷到这篇文章的读者在首次阅读应当跳过红色字体,先通读一读文章全文&…...
光明谷推出AT指令版本的蓝牙音箱SOC 开启便捷智能音频开发新体验
前言 在蓝牙音箱市场竞争日益激烈的当下,开发一款性能卓越且易于上手的蓝牙音箱,成为众多厂商追求的目标。而光明谷科技有限公司推出的 AT 指令版本的蓝牙音箱 SOC,无疑为行业带来了全新的解决方案,以其诸多独特卖点,迅…...
C#从入门到精通(34)—如何防止winform程序被同时打开多次
前言: 大家好,我是上位机马工,硕士毕业4年年入40万,目前在一家自动化公司担任软件经理,从事C#上位机软件开发8年以上!我们在开发上位机软件的过程中,评判一个人软件写的好不好,有一…...
TIP: Flex-DLD
Article: Flex-DLD: Deep Low-Rank Decomposition Model With Flexible Priors for Hyperspectral Image Denoising and Restoration, 2024 TIP. 文章的主要思想是用network来学low-rank decomposition的两个matrix(input是random input). 文章的framew…...
如何在 ubuntu 上使用 Clash 与 docker 开启代理拉起
如何在 ubuntu 上使用 Clash https://github.com/doreamon-design/clash/releases上面是clash 的地址 clash_2.0.24_linux_386.tar.gz 下载 386 的 如果你的电脑是inter tar -xzvf clash_2.0.24_linux_386.tar.gz 启动 ./clash 然后会在电脑上生成一个config的文件 /home/xxx/…...
MFC开发:如何创建第一个MFC应用程序
文章目录 一、概述二、MFC 的主要组件三、创建一个MFC窗口四、控件绑定消息函数 一、概述 MFC 是微软提供的一个 C 类库,用于简化 Windows 应用程序的开发。它封装了 Windows API,提供面向对象的接口,帮助开发者更高效地创建图形用户界面&am…...
react hook useReducer
useReducer useReducer 是 React 中用于状态管理的 Hook,与 useState 不同,它更适合处理复杂的状态逻辑. const [state, dispatch] useReducer(reducer, initialArg, init?) reducer 是一个处理函数,用于更新状态, reducer 里面包含了两个…...
Java与C语言中取模运算符%的区别对比
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: Java 文章目录 💯前言💯C语言中的取模运算符 %基本行为示例 注意事项示例:负数取模 💯Java中的取模运算符 %基本行为示例 对浮点数的支持示例:浮点数取模 符…...
Zabbix 7.2实操指南:基于OpenEuler系统安装Zabbix 7.2
原文出处:乐维社区 部署环境 openEuler 22.03 LTS PHP 8.0 Apache Mysql 8.0 MySQL数据库 6.0 以上版本需要安装mysql8.0以上版本的数据库(以mysql为例子)。 欧拉系统自带 mysql8.0 的源,无需要安装额外的源。 安装mysql …...
Springboot的简单推荐实现
以springboot 推荐社团招新为例子 使用 Spring Boot 构建社团招新推荐系统,用户注册后选择兴趣,系统根据兴趣推荐社团。 实现包括用户注册、兴趣选择和基于标签匹配的推荐算法。 系统使用 JPA 管理数据库,Spring Security 确保安全࿰…...
如何使用Python快速开发一个带管理系统界面的网站-解析方案
如果你想用 Python 开发一个 管理系统界面 的网站,并且希望界面美观,可以考虑以下几个框架和库: 1. Streamlit(快速、简洁) 适合:数据分析、仪表盘、内部管理系统特点: 写法简单,类…...
