C++智能指针概念理解的面试题
C++智能指针概念理解的面试题
第一部分:基础概念
-
解释
std::unique_ptr
和std::shared_ptr
在以下方面的区别:- 所有权语义
- 性能开销
- 自定义删除器的存储方式
- 是否支持数组类型
答案:
所有权语义:
unique_ptr:独占所有权,不能复制,只能移动shared_ptr:共享所有权,通过引用计数管理,可以复制
性能开销:
unique_ptr:几乎无额外开销(等同于原始指针)shared_ptr:有控制块和引用计数的开销
自定义删除器的存储方式:
unique_ptr:删除器是类型的一部分,直接存储在对象中(无额外开销)shared_ptr:删除器存储在控制块中(类型擦除,有额外开销)
是否支持数组类型:
unique_ptr:通过unique_ptr<T[]>显式支持数组shared_ptr:不直接支持数组,需自定义删除器
-
考虑以下代码:
std::shared_ptr<int> p1(new int(42));
std::shared_ptr<int> p2 = std::make_shared<int>(42);
- 这两种初始化方式在内存分配上有何不同?
- 为什么推荐使用
make_shared
? - 在什么情况下不能使用
make_shared
?
答案:
内存分配差异:
shared_ptr<int> p1(new int(42))
:两次分配(对象和控制块分开)make_shared<int>(42)
:一次分配(对象和控制块合并)
推荐make_shared
的原因:
- 更高性能(单次分配)
- 更安全(避免内存泄漏)
- 更好的缓存局部性
不能使用make_shared
的情况:
- 需要自定义删除器
- 需要大括号初始化
- 需要weak_ptr长期存在而对象可被释放的场景
第二部分:深入实现
-
假设C++标准库中没有提供
std::weak_ptr
,你如何仅使用std::shared_ptr
来实现一个弱引用指针?请描述你的设计方案,包括:- 如何检测所指向的对象是否已被释放
- 如何实现
lock()
操作来获取可用的shared_ptr
- 如何避免循环引用
答案:
设计方案:
- 使用
shared_ptr
的引用计数结构扩展 - 添加"弱引用计数"跟踪观察者数量
- 对象释放条件:强引用=0(无论弱引用)
实现lock()
:
- 检查强引用计数>0
- 如果对象存在,增加强引用计数并返回新
shared_ptr
- 否则返回空
shared_ptr
避免循环引用:
- 控制块(control block)通常包含哪些信息?
- 在多线程环境下,引用计数如何保证原子性?
- 为什么
std::shared_ptr
的引用计数使用原子操作而不是简单的整数?
答案:
控制块内容:
- 强引用计数
- 弱引用计数
- 自定义删除器
- 分配器(如使用)
- 指向被管理对象的指针
原子性保证:
- 使用原子操作(如
std::atomic
)修改引用计数 - 内存序保证(通常
memory_order_relaxed
用于计数) - 控制块本身线程安全
使用原子操作的原因:
-
多线程环境下安全修改计数
-
避免数据竞争
-
保证内存可见性
第三部分:高级应用
void file_deleter(FILE* fp) {std::fclose(fp);
}std::unique_ptr<FILE, decltype(&file_deleter)> fp(std::fopen("test.txt", "r"), file_deleter);
- 为什么这里
decltype(&file_deleter)
是必要的? - 如果改用lambda表达式作为删除器,代码应该如何修改?
- 比较
std::unique_ptr
和std::shared_ptr
在自定义删除器存储方式上的差异
答案:
decltype(&file_deleter)
必要性:
unique_ptr
的删除器是类型的一部分- 必须明确指定删除器类型
lambda删除器:
auto deleter = [](FILE* fp) { std::fclose(fp); };
std::unique_ptr<FILE, decltype(deleter)> fp(std::fopen("test.txt", "r"), deleter);
存储方式差异:
-
unique_ptr
:删除器作为模板参数,直接存储 -
shared_ptr
:删除器类型擦除,存储在控制块
struct Base { virtual ~Base() = default; };
struct Derived : Base { /*...*/ };std::shared_ptr<Base> p = std::make_shared<Derived>();
- 解释为什么这个方案是类型安全的
- 如果Base的析构函数不是虚函数,会发生什么?
- 如何设计一个工厂函数,返回基类指针但能正确删除派生类对象?
答案:
类型安全原因:
make_shared
创建完整派生类对象- 虚析构函数确保正确析构顺序
- 共享指针保持完整类型信息
非虚析构函数问题:
- 派生类部分不会被析构
- 资源泄漏
- 未定义行为
工厂函数设计:
template<typename Derived, typename... Args>
std::shared_ptr<Base> create(Args&&... args) {return std::shared_ptr<Base>(new Derived(std::forward<Args>(args)...));
}
第四部分:陷阱与最佳实践
std::shared_ptr<int> create_shared() {int* raw = new int(42);std::shared_ptr<int> p1(raw);std::shared_ptr<int> p2(raw);return p1;
}
- 这段代码会导致什么问题?
- 如何修改才能使其安全?
- 解释为什么
std::enable_shared_from_this
能解决类似问题
答案:
问题:
- 两个
shared_ptr
独立管理同一原始指针 - 会导致双重释放
- 引用计数不共享
修改方案:
std::shared_ptr<int> create_shared() {auto p1 = std::make_shared<int>(42);std::shared_ptr<int> p2 = p1; // 共享所有权return p1;
}
enable_shared_from_this
作用:
-
允许对象安全地生成指向自身的
shared_ptr
-
内部使用weak_ptr避免循环引用
-
确保所有
shared_ptr
共享同一控制块 -
讨论在以下场景中智能指针的使用策略:
- 作为类成员变量
- 在容器中存储动态分配的对象
- 跨线程传递对象所有权
- 与第三方C库交互
答案:
类成员变量:
- 优先
unique_ptr
表达独占 - 需要共享时用
shared_ptr
- 观察用
weak_ptr
容器存储:
- 优先
unique_ptr
(明确所有权) - 需要共享时用
shared_ptr
- 考虑
vector<unique_ptr>
替代vector<Base*>
跨线程传递:
shared_ptr
引用计数线程安全- 对象本身需额外同步
- 避免跨线程传递原始指针
与C库交互:
- 自定义删除器包装C接口
unique_ptr
管理C资源- 注意所有权转移语义
相关文章:
C++智能指针概念理解的面试题
C智能指针概念理解的面试题 第一部分:基础概念 解释std::unique_ptr和std::shared_ptr在以下方面的区别: 所有权语义性能开销自定义删除器的存储方式是否支持数组类型 答案: 所有权语义: unique_ptr:独占所有权&#…...
52.[前端开发-JS实战框架应用]Day03-AJAX-插件开发-备课项目实战-Lodash
常用JavaScript库 1 认识前端工具库 前端工具类库 2 Lodash vs underscore underscore库 VS Lodash库 Lodash库 的安装 Lodash库字符串、数组 Lodash库对象、集合、函数 3 Day.js vs Mement Moment.js库 VS Day.js库 Day.js库安装 Day.js获取、设置、操作时间 Day.js解析、…...
【论文阅读】平滑量化:对大型语言模型进行准确高效的训练后量化
论文题目:SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 论文地址:[2211.10438] SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models 代码地址:http…...
mysql游标分页详解:让分页又快又稳的终极方案
一、什么是游标分页? 游标分页是一种更高效的分页方式,它通过"记住当前位置"而不是"数页码"来实现分页。就像看书时夹书签一样,游标分页会记住你看到哪里了,下次直接从那里继续。 传统分页 vs 游标分页 传…...
图论---染色法(判断是否为二分图)
O(nm) 二分图:可以把所有的点划分到两边,使得边只在集合之间,集合内部没有边。 二分图当且仅当图中不含奇数环(边数为奇数条) #include <iostream> #include <vector> #include <cstring> using …...
算法 | 基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测(附完整matlab代码,公式,原理,可用于毕业论文设计)
以下是一个基于SSA-CNN-LSTM(麻雀算法优化卷积长短期记忆神经网络)的股票价格预测MATLAB项目实例,包含完整代码和详细注释。代码分为数据预处理、模型构建、优化算法、训练预测四个部分。 🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜🚜 1. 数据预处理 %% 数据加…...
在html中如何创建vue自定义组件(以自定义文件上传组件为例,vue2+elementUI)
1、先上代码:vueUpload.js var dom <div class"upload-file"><el-upload :action"uploadFileUrl" :before-upload"handleBeforeUpload" :file-list"fileList" :limit"limit":on-error"handleUpl…...
Asp.Net Core 基于(asp.net core 2.2) 创建asp .net core空项目
文章目录 ASP.NET Core 应用程序的标准入口点,用于配置和启动一个 Web 主机(WebHost)。`InProcess` 代码分析解决 HTTP Error 500.31 - Failed to load ASP.NET Core runtime 的完整方案**`launchSettings.json` 配置文件分析**ASP.NET Core 中的配置源详解ASP.NET Core 应用…...
AiFlutter 低代码平台介绍
产品概述 AiFlutter 低代码平台是一款基于拖拽组件和配置流程图的可视化开发工具,旨在简化移动应用开发过程。无需编写代码,用户即可通过拖拽组件快速搭建应用界面,并通过配置流程图设计页面逻辑。平台支持硬件通信功能,用户可直…...
Flutter Dart 集合类型List Set Map详解军 以及循环语句 forEaclh map where any every
List基础用法 var list1 ["西瓜", "苹果", "香蕉", true, 0];var list2 <String>["西瓜", "苹果", "香蕉"];List list3 ["西瓜", "苹果", "香蕉"];list3.add("草莓&…...
aws(学习笔记第三十九课) iot-msk-pipeline
文章目录 aws(学习笔记第三十九课) iot-msk-pipeline学习内容:1. 整体架构1.1 代码链接1.2 代码调整1.2 整体架构(概要)1.3 整体架构(详细) 2. 代码解析2.1 创建IotProducerDestination2.2 创建IotProducer2.3 创建MSK client的EC22.4 创建MSK cluster2.5 创建Main …...
2025上海车展:赛轮思AI携手行业领军企业展示xUI——混合式、智能体化的AI助理平台
用户将可首次全面体验集成多模态SLM (端侧大语言模型)的Cerence xUl,此次演示由长城汽车和TCL合作呈现 马萨诸塞州伯灵顿,2025年4月22日——Cerence Inc.(NASDAQ: CRNC)(“赛轮思AI”),全球对话…...
聚合分销小程序系统开发方案:整合AI对话、网盘、淘客CPS/CPA、电影票团购与会员卡业务
一、系统架构设计 技术架构 分层设计:采用微服务架构,分为平台层(分销管理、数据库、交易系统)、管理体系层(数据管理、权限控制)和功能层(AI对话、网盘、CPS/CPA拉新、电影票团购、会员卡&…...
设计模式-- 原型模式详解
原型模式(prototype) 原型模式:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象,原型模式属于创造性模式,它同样提供了创建对象的最佳方式之一。(效率很高…...
ARM服务器与X86服务器核心区别分析
ARM服务器与X86服务器核心区别分析 一、架构设计与指令集差异 指令集本质 ARM:基于RISC(精简指令集),指令定长且简单,单周期执行效率高,硬件设计复杂度低,适合低功耗场景。 X86…...
嵌入式:ARM系列分类及主要应用场景
在嵌入式系统和移动计算领域,Arm Cortex 系列处理器凭借其多样化的架构和卓越的性能,成为了众多设备的核心 “大脑”。从高端智能手机到工业控制设备,从物联网终端到安全芯片,Cortex 系列处理器以不同的型号和特性,满足…...
Axure PR 9 中继器 标签
大家好,我是大明同学。 这期内容,我们来了解一下Axure中继器数据表标签交互设计。 预览地址:https://n05kfs.axshare.com 好的,这里就结束了。 我是大明同学。 下期见。...
Django【应用 01】django-plotly-dash安装及使用
django-plotly-dash 的使用文档:https://django-plotly-dash.readthedocs.io/en/stable/introduction.html 以下内容大部分保留原文档的内容,添加实际的步骤和必要的说明。 django-plotly-dash安装及使用 1.安装配置1.1 安装1.2 注册组件1.3 配置框架1.…...
【MFC】 VS2022打开低版本的MFC,双击.rc文件,DIalog加载失败,页面弹窗fatal error RC***:cannot open*****
打开以前的MFC示例报错,打开VS2019的实例以及更早VS版本的实例都一样,打不开,还报错; 错误 MSB8041 此项目需要 MFC 库。从 Visual Studio 安装程序(单个组件选项卡)为正在使用的任何工具集和体系结构安装它们。 GxCameraEvents_VS2015 C:\P…...
ClickHouse 中`MergeTree` 和 `ReplicatedMergeTree`表引擎区别
在 ClickHouse 中,MergeTree 和 ReplicatedMergeTree 都是用于存储和管理数据的表引擎,但它们的主要区别在于是否支持数据复制。下面详细解释两者的不同点及其适用场景。 MergeTree 定义: MergeTree 是 ClickHouse 中最基本的表引擎之一&a…...
PubMed PDF下载 cloudpmc-viewer-pow逆向
目标:https://pmc.ncbi.nlm.nih.gov/articles/ pdf的下载链接是直接存在的 但是第一次单击下载不会触发PDF下载,而是跳转到验证页面然后又跳回概览页面 再次点击下载按钮,PDF就能正常下载了。现在要分析下载PDF要验证什么,如cooki…...
C语言面试高频题——strcat、strncat、strcmp、strcpy 哪些函数会导致内存溢出?
1. 函数功能与内存溢出风险 (1) strcat 功能:将源字符串追加到目标字符串的末尾。 原型: char *strcat(char *dest, const char *src);内存溢出风险: strcat 不会检查目标缓冲区的大小,直接将源字符串追加到目标字符串后。如果目…...
Linux套接字+Sqlite实例:客户端-服务器应用程序教程
本文将详细介绍如何创建一个基于客户端-服务器架构的应用程序,实现用户注册、登录、单词查询以及历史记录查询。该应用通过TCP套接字进行客户端和服务器之间的通信,并通过SQLite数据库进行用户和查询记录的管理。教程会逐步解析客户端和服务器端的实现&a…...
用 Python 打造打篮球字符动画!控制台彩色炫酷输出,抖音搞怪视频灵感还原
一、引言:从抖音搞怪视频到 Python 字符动画的奇妙之旅 刷抖音时刷到一个神级操作 —— 博主用 01 数字矩阵还原了明星打篮球的经典画面,字符在控制台随动作节奏炫彩跳动,瞬间点燃了技术宅的 DNA!作为 Python 图像处理爱好者&…...
入侵检测系统(IDS)与入侵防御系统(IPS):功能对比与部署实践
入侵检测系统(IDS)与入侵防御系统(IPS):功能对比与部署实践 在网络安全防御体系中,入侵检测系统(Intrusion Detection System, IDS)与入侵防御系统(Intrusion Preventio…...
力扣-hot100(找到字符串中的所有字母异位词)
438. 找到字符串中所有字母异位词 中等 给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0…...
零信任架构:重塑网络安全的IT新范式
在信息技术(IT)的风云变幻中,网络安全领域正迎来一场深刻变革——零信任架构(Zero Trust Architecture)。2025年,随着远程办公的常态化、云服务的普及以及网络攻击的日益复杂化,传统的“城堡与护…...
大模型微调 - transformer架构
什么是Transformer Transformer 架构是由 Vaswani 等人在 2017 年提出的一种深度学习模型架构,首次发表于论文《Attention is All You Need》中 Transformer 的结构 Transformer 编码器(Encoder) 解码器(Decoder) …...
Python图形界面编程(二)
目录 六、控件属性和事件响应 1、基本的操控 2、示例 七、对话框 六、控件属性和事件响应 1、基本的操控 有的控件有对对应的函数,可以用来设置以及获取属性或者设置属性,或者以字典下标的形式来获取,设置对应的属性: 比如&…...
MongoDB 图片 URL 存储异常问题解决方案
项目场景: 在开发一个在线考试系统时,前端需要提交学生的答题截图到后端,后端使用 MinIO 存储图片并保存图片 URL 到 MongoDB 数据库。系统需要支持多次提交图片,并将所有图片 URL 以数组形式存储在 MongoDB 的 screenShot 字段中…...
run code执行ts配置
1、全局安装typescript npm install –g typescript 执行tsc –v,可输出版本号,代表安装成功 2、创建tsConfig文件 npx tsc –init 创建成功目录下会出现tsconfig.json文件 3、安装ts-node,支持执行运行ts文件 npm install –g ts-node 控制…...
Python 虚拟环境管理:venv 与 conda 的选择与配置
文章目录 前言一、虚拟环境的核心价值1.1 依赖冲突的典型场景1.2 隔离机制实现原理 二、venv 与 conda 的架构对比2.1 工具定位差异2.2 性能基准测试(以创建环境 安装 numpy 为例) 三、venv 的配置与最佳实践3.1 基础工作流3.2 多版本 Python 管理 四、…...
【前缀和计算和+哈希表查找次数】Leetcode 560. 和为 K 的子数组
题目要求 给定一个整数数组 nums 和一个整数 k,统计并返回该数组中和为 k 的子数组的个数。 子数组是数组中元素的连续非空序列。 示例 1 输入:nums [1, 1, 1], k 2 输出:2 示例 2 输入:nums [1, 2, 3], k 3 输出…...
[原创](现代Delphi 12指南):[macOS 64bit App开发]:如何使用CFStringRef类型字符串?
[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...
89.WPF 中实现便捷的数字输入框:DecimalUpDown 控件的使用 WPF例子 C#例子.
在 WPF 开发中,经常会遇到需要用户输入数字的场景。为了提供更好的用户体验,我们可以使用一个功能强大的控件——DecimalUpDown,它来自第三方库 Extended WPF Toolkit。这个控件不仅支持用户通过键盘输入数字,还支持通过鼠标滚轮或…...
【时时三省】(C语言基础)循环程序举例
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 例题: 用公式4/π≈1-3/1+5/1-7/1+...求π的近似值,直到发现某一项的绝对值小于10的-6次方为止(该项不累加)。 解题思路: 这是求值的近似方法中的一种。求π值可以用不同的近似方法。如下面的表达式都可以…...
Linux常用中间件命令大全
1.nginx 执行命令之前需要先进入sbin目录查看nginx版本: ./nginx -v检查配置文件正确性: ./nginx -t启动nginx服务: ./nginx停止nginx服务: ./nginx -s stop启动完成后可以查看nginx进程: ps -ef|grep nginx可以通过绝…...
数图信息科技邀您共赴第二十五届中国零售业博览会
数图信息科技邀您共赴第二十五届中国零售业博览会 2025年5月8日至10日,数图信息科技将精彩亮相第二十五届中国零售业博览会(CHINASHOP 2025),与行业伙伴共探零售数字化转型新机遇! 数图展会新品抢先看 数图商品一…...
路由器的基础配置全解析:静态动态路由 + 华为 ENSP 命令大全
🚀 路由器的基础配置全解析:静态&动态路由 华为 ENSP 命令大全 🌐 路由器的基本概念📍 静态路由配置📡 动态路由协议:RIP、OSPF、BGP🖥 华为 ENSP 路由器命令大全🔹 路由器基本…...
「Java EE开发指南」如何使用MyEclipse的可视化JSF编辑器设计JSP?(一)
本教程介绍在MyEclipse中开发EJB 3无状态会话bean,由于JPA实体和EJB 3实体非常相似,因此本教程不涉及EJB 3实体Bean的开发。在本教程中,您将学习如何: Visual JSF Designer(可视化JSF设计器)的目标是使创建…...
【设计】接口幂等性设计
1. 幂等性定义 接口幂等性: 无论调用次数多少,对系统状态的影响与单次调用相同。 比如用户支付接口因网络延迟重复提交了三次。 导致原因: 用户不可靠(手抖多点)网络不可靠(超时重传)系统不可…...
深入理解机器学习:人工智能的核心驱动力
在当今数字化时代,机器学习作为人工智能领域的关键技术,正以前所未有的速度改变着我们的生活和工作方式。从智能语音助手到精准的医疗诊断,从个性化的推荐系统到自动驾驶汽车,机器学习的应用无处不在,其影响力深远而广…...
CI/CD自动化部署(持续集成和持续交付/部署)
持续集成:开发人员频繁地将代码集成到共享仓库,然后自动运行测试持续交付:自动准备好发布,但需要手动触发部署持续部署:完全自动化的,不需要人工干预 流程: 比如,当开发人员提交代…...
如何理解计算机网卡完成数据传输的串并转换
计算机网卡的串并转换(串行-并行转换)是网络通信中的一个关键硬件功能,主要涉及数据的传输形式转换。它的核心目的是解决计算机内部处理数据的方式(并行)与网络传输数据的方式(串行)之间的差异。以下是通俗易懂的解释: 1. 串行传输 vs. 并行传输 并行传输: 计算机内部…...
基于Axure的动态甘特图设计:实现任务增删改与时间拖拽交互
甘特图作为项目管理核心工具,其动态交互能力直接关系到团队协作效率。本文以Axure RP 9为载体,通过中继器(Repeater)与动态面板(Dynamic Panel)的深度结合,设计一款支持任务名称动态编辑、时间轴…...
XMOS空间音频——在任何设备上都能提供3D沉浸式空间音频且实现更安全地聆听
2025年3月,全球规模最大的嵌入式行业盛会——德国纽伦堡国际嵌入式展(Embedded World 2025,EW 25)圆满落幕。在这场汇聚全球 950 家展商、3 万余专业观众的科技盛宴中,XMOS 展位人头攒动,多款尖端产品和多…...
使用功能包组织C++节点的具体教程
在 ROS(Robot Operating System)中,使用功能包(package)来组织 C 节点是一种常见且有效的方式,它能让代码结构更清晰、便于管理和复用。 1. 环境准备 确保已经安装了 ROS,这里以 ROS 2 Humble…...
免费的车牌势识别系统
背景 就是想要一个车牌识别系统 直接上教程 需要首先安装python3 然后执行下面的命令 pip install hyperlpr3 lpr3 rest --port 9999 --host 0.0.0.0 --workers 1 访问地址地址 # 9999 与上述端口一致 http://你的ip:9999/api/v1/docs 测试效果 准备一张图片 lpr3 sa…...
微信小程序蓝牙连接打印机打印单据完整Demo【蓝牙小票打印】
文章目录 一、准备工作1. 硬件准备2. 开发环境 二、小程序配置1. 修改app.json 三、完整代码实现1. pages/index/index.wxml2. pages/index/index.wxss3. pages/index/index.js 四、ESC/POS指令说明五、测试流程六、常见问题解决七、进一步优化建议 下面我将提供一个完整的微信…...
阿里云基于本地知识库构建RAG应用 | 架构与场景
RAG(检索增强生成,Retrieval-Augmented Generation)是一种结合了检索和生成技术的框架,旨在通过外部知识库的检索来增强大语言模型(LLM)的生成能力。 其核心架构包括两个主要部分: 检索模块&a…...