当前位置: 首页 > news >正文

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++|经典代码题(动态资源的双重释放与「按值传递、按引用传递、智能指针的使用」)

以下代码中你能看出其存在什么问题&#xff1f;如何修复&#xff0c;能给出几种方法&#xff1f;分别在什么场景下用哪种方法。 #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.目录操作&#xff1a; ls&#xff1a;列出目录内容。cd&#xff1a;改变当前工作目录。pwd&#xff1a;显示当前工作目录的路径。mkdir&#xff1a;创建新目录。rmd…...

Kubectl基础命令使用

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

推荐编译器插件:Fitten Code 更快更好的AI助手

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…...

ArcGIS Pro基础:状态栏显示栏的比例尺设置和经纬度位置

上图所示&#xff0c;界面下方最左侧是显示的比例尺&#xff0c;可以进行选择设置&#xff0c;也可以进行自定义设置 上图所示&#xff0c;可以手动录入比例尺&#xff0c;同时也可以对比例尺设置别名&#xff0c;比如【实验1】作为特定比例尺的标记 如上图所示&#xff0c;可以…...

微前端架构入门

什么是微前端? 定义 微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。 微前端是一种架构风格,它允许将一个复杂的大前端应用拆分成多个可以独立开发、部署的小型前端应用。这些小型前端应用通常被称为“子应用”或者“微前端应用…...

[LitCTF 2023]导弹迷踪

页面源码底部有多个js,查看浏览 查看ksrc/game.js发现flag...

win10安装wsl2(ubuntu20.04)并安装 TensorRT-8.6.1.6、cuda_11.6、cudnn

参考博客&#xff1a; 1. CUDA】如何在 windows 上安装 Ollama 3 open webui &#xff08;docker WSL 2 ubuntu nvidia-container&#xff09;&#xff1a;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 学习第六天:页面布局

如何设计页面&#xff1f; 有个类似沙盒模式的玩法&#xff0c;Qt Widget Designer可以更好的帮助我们设计页面 点击.ui文件进入 右上方可以看到四种常见的布局&#xff1a; 四种布局 &#xff08;一&#xff09;水平布局horizontalLayout&#xff1a;QHBoxLayout H 是 hori…...

利用队列收集单双击和长按按键

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

AI工作流:低代码时代的革新者,重塑手机问答类应用生态

在这个数字化迅猛发展的时代&#xff0c;低代码技术正以惊人的速度改变着我们的生活方式。作为低代码人群的先锋&#xff0c;AI工作流技术正在以前所未有的方式&#xff0c;赋予非技术人群实现梦想的能力 &#x1f525;能用AI-低代码传送门&#xff1a;https://www.nyai.chat …...

配置MySQL主从,配置MySQL主主 +keeplive高可用

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

第5节:Elasticsearch核心概念

我的后端学习笔记大纲 我的ElasticSearch学习大纲 1.Lucene和Elasticsearch的关系: 1.Lucene&#xff1a;最先进、功能最强大的搜索库&#xff0c;直接基于lucene开发&#xff0c;非常复杂&#xff0c;api复杂2.Elasticsearch&#xff1a;基于lucene&#xff0c;封装了许多luc…...

存储实验:华为异构存储在线接管与在线数据迁移(Smart Virtualization Smart Migration 特性)

目录 目的实验环境实验步骤参考文档1. 主机安装存储多路径2. v2存储创建Lun&#xff0c;映射给主机&#xff1b;主机分区格式化&#xff0c;写数据3. 将v2存储映射该成映射到v3存储上(v3存储和v2之间链路搭建&#xff0c;测通&#xff0c;远端设备&#xff09;&#xff08;Smar…...

职业院校云计算实训室建设方案全景剖析

在信息化社会的今天&#xff0c;云计算作为一项关键技术&#xff0c;正在迅速改变着教育和培训的方式。本文旨在探讨如何通过"职业院校云计算实训室建设方案"&#xff0c;为学生提供一个现代化、高效的学习和研究环境&#xff0c;以适应云计算技术的发展和市场需求。…...

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中将数据库查询结果转换为枚举类型

前言 在开发过程中&#xff0c;我们经常需要将从数据库获取的字符串或数字转换为更具语义的枚举类型。这不仅可以提高代码的可读性&#xff0c;还可以确保类型安全。这时候我们从数据库查出来的值如何通过枚举转换返回&#xff1f; 1. 构建枚举类型 首先&#xff0c;我们需要…...

秋招突击——8、20——知识补充——Java容器

文章目录 引言正文总览ArrayListLinkedListQueue & Stack & ArrayDequePriorityQueue![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/acdc7f306a2e4052bc6bc14a175e67fc.png)HashSet & HashMapLinkedHashSet & LinkedHashMapTreeSet & TreeMap 面…...

IOS 06 OC调用Swift第三方框架

前面文章05讲的是在OC项目中&#xff0c;调用Swift代码&#xff0c;而在真实开发过程中&#xff0c;在OC项目中调用Swift第三方框架场景用的是非常多的&#xff0c;所以我们也了解在OC项目如何使用Swift写的三方框架。 实现流程&#xff1a; 1、OCUseSwiftTest&#xff1b;在…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

HashMap中的put方法执行流程(流程图)

1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中&#xff0c;其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下&#xff1a; 初始判断与哈希计算&#xff1a; 首先&#xff0c;putVal 方法会检查当前的 table&#xff08;也就…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...