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;在…...
告别showSoftInput失效:一文读懂Android 11+的WindowInsetsController输入法控制
Android输入法控制演进:从InputMethodManager到WindowInsetsController的深度解析 在移动应用开发中,输入法交互是最基础却又最容易被忽视的细节之一。许多开发者都曾遇到过这样的场景:精心设计的登录界面,光标在输入框闪烁&#…...
城通网盘高速解析终极指南:如何免费实现40倍下载提速
城通网盘高速解析终极指南:如何免费实现40倍下载提速 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 你是否厌倦了城通网盘那令人抓狂的蜗牛下载速度?每次下载大文件都要面对漫长…...
平衡车PID积分饱和问题
你发现了PID最致命的坑! 你说的完全正确:积分(Ki)是累加的,会无限叠加,直接让PWM爆掉、车猛冲、失控! 这就是积分饱和 —— 99%初学者死在这里。 我现在彻底讲透积分为什么炸、怎么修复、平衡车…...
JetBrains IDE 30天试用重置:一键解决方案的完整实践指南
JetBrains IDE 30天试用重置:一键解决方案的完整实践指南 【免费下载链接】ide-eval-resetter 项目地址: https://gitcode.com/gh_mirrors/id/ide-eval-resetter 当您正专注于代码调试时,IDE突然弹出"评估期已结束"的红色警告…...
开源办公套件自动化部署与集成实战:基于OpenOffice的服务化解决方案
1. 项目概述:为什么我们需要一个“开源”的办公套件?如果你在GitHub上搜索过办公软件相关的仓库,大概率会看到过longyangxi/OpenOffice这个项目。乍一看,你可能会以为这是一个Apache OpenOffice的镜像或者某个分支。但点进去仔细研…...
DownKyi技术架构解析:构建高性能B站视频下载引擎的工程实践
DownKyi技术架构解析:构建高性能B站视频下载引擎的工程实践 【免费下载链接】downkyi 哔哩下载姬downkyi,哔哩哔哩网站视频下载工具,支持批量下载,支持8K、HDR、杜比视界,提供工具箱(音视频提取、去水印等&…...
基于 Next.js 的无头电商架构实战:从 Vercel Commerce 看现代全栈开发
1. 项目概述:一个面向未来的全栈电商起点如果你最近在琢磨着用 Next.js 搞一个电商网站,或者想找一个现代、开箱即用的全栈电商模板来启动项目,那你大概率已经听说过vercel/commerce这个仓库了。它不是某个具体的电商平台,而是一个…...
CN2628 可用太阳能供电 5 伏特低压差电压调制集成电路
概述: CN2628是一款可用太阳能供电的低噪声线性电压调制集成电路,采用固定5.0V输出电压,最大 输出电流可达1安培,在5.5V到7V的输入电压范围内输出电压精度可达1%。CN2628工作电流只有520微安,而且同输入和输出的压差没有关系。 CN…...
Windows上运行Swift代码的三种实战路径
1. 为什么Windows开发者需要Swift? Swift作为苹果生态的主力编程语言,近年来在服务端开发、机器学习等领域的应用越来越广泛。但很多刚接触Swift的Windows开发者会发现:官方文档里压根没提Windows支持!这其实是因为Swift最初就是…...
OpenClaw实战教程:声明式配置驱动的高效数据抓取方案
1. 项目概述:一个关于“OpenClaw”的实战教程 最近在GitHub上看到一个挺有意思的项目,叫“OpenClawTuto”。光看名字,你可能会有点摸不着头脑,这“OpenClaw”到底是个啥?是某种开源机械爪?还是一个代号&…...
