C/C++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)
以下代码中你能看出其存在什么问题?如何修复,能给出几种方法?分别在什么场景下用哪种方法。
#include <iostream>class Buffer {public:Buffer() { std::cout << "Buffer created" << std::endl; }~Buffer() { std::cout << "Buffer destroyed" << std::endl; }Buffer(const Buffer&) = delete;Buffer& operator=(const Buffer&) = delete;
};class BufferManager {public:BufferManager() : buffer(new Buffer()) {std::cout << "BufferManager created" << std::endl;}~BufferManager() {std::cout << "BufferManager destroyed" << std::endl;delete buffer;}private:Buffer* buffer;
};void getBuffer(BufferManager manager) {std::cout << "Call getBuffer" << std::endl;
}int main() {BufferManager manager;getBuffer(manager);return 0;
}
代码简单介绍如下:给出两个类,一个是 buffer 管理器,底层是 buffer, buffer 管理器持有一个 buffer 指针,有一个 getBuffer 函数。主逻辑也很简单,就是构造 BufferManager,调用 getBuffer
我们简单分析一下代码:
我们在 getBuffer 中,是按值传递 BufferManager
对象,这会导致 BufferManager
对象被拷贝。然而, BufferManager 对象中报一个只想动态分配内存的 buffer ,并且 BufferManager 的默认拷贝构造函数只是执行浅拷贝。这样,多个 BufferManager 对象会共享同一个 Buffer 对象指针。当它们被销毁时,析构函数会多次尝试删除同一个指针,导致双重释放错误。
拷贝构造函数和赋值运算符的隐式生成会默认浅拷贝!!这对于类中包含指针成员时,通常会导致资源管理问题。
方案一:禁止拷贝构造和赋值操作
主要场景: 如果 BufferManager 作为资源的唯一拥有者,不应允许拷贝,则可以直接禁止拷贝构造函数和赋值操作符。这样就可以避免拷贝行为带来的问题。
class BufferManager {public:BufferManager() : buffer(new Buffer()) {std::cout << "BufferManager created" << std::endl;}~BufferManager() {std::cout << "BufferManager destroyed" << std::endl;delete buffer;}// 禁止拷贝构造和赋值操作BufferManager(const BufferManager&) = delete;BufferManager& operator=(const BufferManager&) = delete;private:Buffer* buffer;
};
通过禁止拷贝和赋值操作,BufferManager 对象无法被复制,因此也不会出现指针重复管理的问题。在需要确保对象不可拷贝的场景下使用这种方法非常合适,例如管理独占资源时。
方式二:按引用传递 BufferManager(最普遍、广泛的改进)
场景:如果只需要传递 BufferManager 的引用,而不需要拷贝整个对象,可以使用按引用传递的方式。这可以避免对象的拷贝,消除双重释放的风险。
void getBuffer(BufferManager& manager) {}
方式三:使用智能指针(也是一种普遍、广泛的改进)
场景:如果希望让对象能够被安全地复制和转移,并且自动管理指针的生命周期,可以使用 std::unique_ptr 代替原始指针。std::unique_ptr 能够确保指针只被释放一次,并且不会导致双重释放问题。
我们将 BufferManager 中的原始指针替换为 std::unique_ptr,这样当 BufferManager 被销毁时,智能指针会自动管理 Buffer 对象的销毁。
#include <memory>class BufferManager {public:BufferManager() : buffer(std::make_unique<Buffer>()) {std::cout << "BufferManager created" << std::endl;}~BufferManager() {std::cout << "BufferManager destroyed" << std::endl;}private:std::unique_ptr<Buffer> buffer;
};
相关文章:
C/C++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)
以下代码中你能看出其存在什么问题?如何修复,能给出几种方法?分别在什么场景下用哪种方法。 #include <iostream>class Buffer {public:Buffer() { std::cout << "Buffer created" << std::endl; }~Buffer() { s…...
西北乱跑娃 -- linux使用笔记
1.后台运行每天一个日志文件 nohup python3.8 manage.py >> $(date %Y-%m-%d).log 2>&1 &2.目录操作: ls:列出目录内容。cd:改变当前工作目录。pwd:显示当前工作目录的路径。mkdir:创建新目录。rmd…...

Kubectl基础命令使用
一.Kubectl 基础命令 格式: kubectl [command] [TYPE] [NAME] [FLAGS] kubectl 是 Kubernetes 的命令行工具,用于管理 Kubernetes 集群。以下是一些常用的 kubectl 命令及其选项: 常用命令 获取资源 列出所有资源类型(Pods、De…...

推荐编译器插件:Fitten Code 更快更好的AI助手
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...

ArcGIS Pro基础:状态栏显示栏的比例尺设置和经纬度位置
上图所示,界面下方最左侧是显示的比例尺,可以进行选择设置,也可以进行自定义设置 上图所示,可以手动录入比例尺,同时也可以对比例尺设置别名,比如【实验1】作为特定比例尺的标记 如上图所示,可以…...
微前端架构入门
什么是微前端? 定义 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。 微前端是一种架构风格,它允许将一个复杂的大前端应用拆分成多个可以独立开发、部署的小型前端应用。这些小型前端应用通常被称为“子应用”或者“微前端应用…...

[LitCTF 2023]导弹迷踪
页面源码底部有多个js,查看浏览 查看ksrc/game.js发现flag...
win10安装wsl2(ubuntu20.04)并安装 TensorRT-8.6.1.6、cuda_11.6、cudnn
参考博客: 1. CUDA】如何在 windows 上安装 Ollama 3 open webui (docker WSL 2 ubuntu nvidia-container):https://blog.csdn.net/smileyan9/article/details/140391667 2. 在 Windows 10 上 安装 W…...

信息搜集--敏感文件Banner
免责声明:本文仅做分享参考... 目录 git安装: git目录结构: 敏感目录泄露 1-git泄露 (1)常规git泄露 scrabble工具 (2)git回滚 (3)git分支 GitHacker工具 (4)git泄露的其他利用 .git重定向问题 2-SVN泄露 dvcs-ripper工具 3-小结 dirsearch目录扫描工具 敏感备…...

Qt 学习第六天:页面布局
如何设计页面? 有个类似沙盒模式的玩法,Qt Widget Designer可以更好的帮助我们设计页面 点击.ui文件进入 右上方可以看到四种常见的布局: 四种布局 (一)水平布局horizontalLayout:QHBoxLayout H 是 hori…...

利用队列收集单双击和长按按键
利用队列收集单双击和长按按键 引言 当我们仅仅通过在while循环里面进行判断按键类型的标志位, 然后进行操作的时候, 我们的最小例程很小, 所以能够实时的检测到按键,从而触发实验现象. 假如我们此时进入了一个事件处理函数呢 ? 并且这个这个函数的操作是不可被打断的, 如果此…...

AI工作流:低代码时代的革新者,重塑手机问答类应用生态
在这个数字化迅猛发展的时代,低代码技术正以惊人的速度改变着我们的生活方式。作为低代码人群的先锋,AI工作流技术正在以前所未有的方式,赋予非技术人群实现梦想的能力 🔥能用AI-低代码传送门:https://www.nyai.chat …...

配置MySQL主从,配置MySQL主主 +keeplive高可用
在大数据-Hadoop体系中 配置MySQL主主keeplive高可用 注意:这个是我两年前的word文档,可以当作参考文档有个思路参考一下,但是里面可能有些地方有误 另外 :关于一些企业级实战技术可以参考这篇mysql 物理备份 MySQL 全量备份 增量备份 差异…...

第5节:Elasticsearch核心概念
我的后端学习笔记大纲 我的ElasticSearch学习大纲 1.Lucene和Elasticsearch的关系: 1.Lucene:最先进、功能最强大的搜索库,直接基于lucene开发,非常复杂,api复杂2.Elasticsearch:基于lucene,封装了许多luc…...

存储实验:华为异构存储在线接管与在线数据迁移(Smart Virtualization Smart Migration 特性)
目录 目的实验环境实验步骤参考文档1. 主机安装存储多路径2. v2存储创建Lun,映射给主机;主机分区格式化,写数据3. 将v2存储映射该成映射到v3存储上(v3存储和v2之间链路搭建,测通,远端设备)(Smar…...

职业院校云计算实训室建设方案全景剖析
在信息化社会的今天,云计算作为一项关键技术,正在迅速改变着教育和培训的方式。本文旨在探讨如何通过"职业院校云计算实训室建设方案",为学生提供一个现代化、高效的学习和研究环境,以适应云计算技术的发展和市场需求。…...
VS Code安装与vue项目新建
1、下载安装node.js、VS Code node.js官网下载 Visual Studio Code官网下载 # 查看node.js是否安装成功 node -v npm -v # 定义镜像路径 npm config set registry https://registry.npmmirror.com # 查看是否配置成功 npm config get# 安装webpack npm install webpack -g #…...
如何在Java中将数据库查询结果转换为枚举类型
前言 在开发过程中,我们经常需要将从数据库获取的字符串或数字转换为更具语义的枚举类型。这不仅可以提高代码的可读性,还可以确保类型安全。这时候我们从数据库查出来的值如何通过枚举转换返回? 1. 构建枚举类型 首先,我们需要…...

秋招突击——8、20——知识补充——Java容器
文章目录 引言正文总览ArrayListLinkedListQueue & Stack & ArrayDequePriorityQueueHashSet & HashMapLinkedHashSet & LinkedHashMapTreeSet & TreeMap 面…...
IOS 06 OC调用Swift第三方框架
前面文章05讲的是在OC项目中,调用Swift代码,而在真实开发过程中,在OC项目中调用Swift第三方框架场景用的是非常多的,所以我们也了解在OC项目如何使用Swift写的三方框架。 实现流程: 1、OCUseSwiftTest;在…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...

解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...