一、核心概念深入解析

news2025/6/5 22:46:14

一、核心概念深入解析

1. shared_ptr 的线程安全性澄清
  • 引用计数是原子操作shared_ptr 的引用计数(use_count)在多线程中递增 / 递减是安全的(原子操作),但对象本身的读写需额外同步(如 std::mutex)。
  • 误区纠正:线程安全仅针对计数管理,若多个线程同时修改对象数据,仍需加锁避免数据竞争。
2. shared_ptr 构造方式对比
方式示例安全性性能推荐度
直接构造(显式)shared_ptr<int> p(new int(42));需避免裸指针重复使用中等★★☆☆☆
工厂函数 make_sharedauto p = make_shared<int>(42);安全(避免裸指针)优(单次分配)★★★★★
拷贝 / 移动构造shared_ptr<int> p2 = p1;安全★★★★☆

  • make_shared 优势
    • 减少内存分配次数(对象和控制块一次分配)。
    • 避免表达式求值顺序导致的潜在泄漏(如 shared_ptr(populate(), commit()) 中若 populate 抛异常,commit 可能未调用)。
3. 删除器(Deleter)的高级用法
  • 类型:可以是函数指针、lambda、函数对象。
  • 示例:lambda 删除器

    cpp

    shared_ptr<FILE> file(fopen("test.txt", "w"), 
                         [](FILE* fp) { fclose(fp); cout << "File closed\n"; });
    
  • 数组管理

    cpp

    shared_ptr<int> arr(new int[5], [](int* p) { delete[] p; }); // 自定义删除器处理数组
    
4. 循环引用的本质与解决
  • 场景:双向链表节点互相持有 shared_ptr

    cpp

    class Node {
    public:
        shared_ptr<Node> next;
        shared_ptr<Node> prev;
        ~Node() { cout << "Node destroyed\n"; }
    };
    
    int main() {
        auto a = make_shared<Node>();
        auto b = make_shared<Node>();
        a->next = b; // a强引用b(b计数+1)
        b->prev = a; // b强引用a(a计数+1)
        // 离开作用域时,a和b计数均为1(循环引用),无法释放 → 内存泄漏
    }
    
  • 解决方案:用 weak_ptr 打破强引用

    cpp

    class Node {
    public:
        shared_ptr<Node> next;
        weak_ptr<Node> prev; // 弱引用,不影响计数
        ~Node() { cout << "Node destroyed\n"; }
    };
    // 此时,a和b计数均为1,离开作用域时正常释放
    
5. weak_ptr 的核心特性
  • 不影响引用计数weak_ptr 构造 / 赋值时,shared_ptr 计数不变。
  • 访问数据的唯一方式

    cpp

    weak_ptr<int> wp(sp); // wp观察sp
    if (auto tmp = wp.lock()) { // 转换为shared_ptr,非空时访问
        cout << *tmp << endl;
    }
    
  • 用途
    • 避免循环引用。
    • 实现 “观察者模式”(观察共享资源是否存在)。
    • 缓存(如缓存对象,存在时直接使用,不存在时重建)。

二、面试高频问题与回答模板

问题 1:shared_ptr 循环引用是什么?如何解决?

回答
循环引用指两个或多个 shared_ptr 互相强引用,导致引用计数无法归零,内存无法释放。
示例:双向链表节点互相持有 shared_ptr,形成环。
解决方案
将其中一个引用改为 weak_ptr(弱引用),weak_ptr 不增加计数,打破循环。

cpp

class Node {
public:
    shared_ptr<Node> next;
    weak_ptr<Node> prev; // 弱引用
};
问题 2:weak_ptr 有什么作用?如何访问其指向的数据?

回答
weak_ptr 是 shared_ptr 的辅助类,用于:

  1. 解决循环引用(弱引用不影响计数)。
  2. 观察 shared_ptr 是否存在(通过 lock() 检查)。
    访问数据步骤

cpp

weak_ptr<int> wp(sp); // 关联shared_ptr
if (auto locked_sp = wp.lock()) { // 转换为shared_ptr,非空时有效
    cout << *locked_sp << endl; // 通过shared_ptr访问
}
问题 3:shared_ptr 和 unique_ptr 的区别?

回答

特性shared_ptrunique_ptr
所有权共享(多个指针指向同一资源)独占(唯一所有权)
引用计数
拷贝 / 赋值允许(计数变化)禁止(仅可移动)
适合场景多指针共享资源独占资源(如函数返回值)
性能稍低(计数开销)更高
问题 4:为什么推荐使用 make_shared 而非直接 new?

回答

  1. 性能优化make_shared 一次分配内存(对象 + 控制块),减少 new 和 delete 次数。
  2. 异常安全:避免表达式求值顺序导致的资源泄漏(如 shared_ptr(populate(), commit()) 中若 populate 抛异常,commit 可能未调用,而 make_shared 无此问题)。
  3. 代码简洁:自动推导类型,无需显式指定模板参数(auto 配合使用)。
问题 5:shared_ptr 如何管理非堆内存资源(如文件句柄)?

回答
通过自定义删除器指定释放逻辑,而非默认的 delete
示例

cpp

void fclose_deleter(FILE* fp) { fclose(fp); }
shared_ptr<FILE> file(fopen("test.txt", "r"), fclose_deleter);
// 或用lambda:
// shared_ptr<FILE> file(fopen("test.txt", "r"), [](FILE* fp){ fclose(fp); });

三、总结:面试核心考点

  1. shared_ptr 原理:引用计数、RAII、线程安全边界(计数安全,对象操作需同步)。
  2. 最佳实践:优先 make_shared,避免裸指针,用 weak_ptr 解决循环引用。
  3. weak_ptr 定位:辅助 shared_ptr,仅观察不持有资源,需通过 lock() 访问数据。
  4. 场景题:能结合双向链表等场景,分析循环引用成因并给出解决方案。

通过以上梳理,可系统掌握 shared_ptr/weak_ptr 的核心知识,从容应对面试中的原理分析与场景题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2397949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Idea 配置 Maven 环境

下载 Maven 官网&#xff1a;https://maven.apache.org/index.html 点击左侧 Downloads&#xff0c;然后选择 Files 中的 zip 包下载&#xff08;下载慢可以使用迅雷&#xff09; 配置 Maven 将压缩包解压&#xff0c;比如我解压后放到了 D:\developer\environment\apache-…

Kafka 如何保证不重复消费

在消息队列的使用场景中&#xff0c;避免消息重复消费是保障数据准确性和业务逻辑正确性的关键。对于 Kafka 而言&#xff0c;保证不重复消费并非单一机制就能实现&#xff0c;而是需要从生产者、消费者以及业务层等多个维度协同配合。接下来&#xff0c;我们将结合图文详细解析…

RNN结构扩展与改进:从简单循环网络到时间间隔网络的技术演进

本文系统介绍 RNN 结构的常见扩展与改进方案。涵盖 简单循环神经网络&#xff08;SRN&#xff09;、双向循环神经网络&#xff08;BRNN&#xff09;、深度循环神经网络&#xff08;Deep RNN&#xff09; 等多种变体&#xff0c;解析其核心架构、技术特点及应用场景&#xff0c;…

类 Excel 数据填报

类 Excel 填报模式&#xff0c;满足用户 Excel 使用习惯 数据填报&#xff0c;可作为独立的功能模块&#xff0c;用于管理业务流程、汇总采集数据&#xff0c;以及开发各类数据报送系统&#xff0c;因此&#xff0c;对于报表工具而言&#xff0c;其典型场景之一就是利用报表模…

Office文档图片批量导出工具

软件介绍 本文介绍一款专业的Office文档图片批量导出工具。 软件特点 这款软件能够批量导出Word、Excel和PPT中的图片&#xff0c;采用绿色单文件设计&#xff0c;体积小巧仅344KB。 基本操作流程 使用方法十分简单&#xff1a;直接将Word、Excel或PPT文件拖入软件&#xf…

【iOS】ARC 与 Autorelease

ARC 与 Autorelease 文章目录 ARC 与 Autorelease前言何为ARC内存管理考虑方式自己生成的对象,自己持有非自己生成的对象,自己也可以持有不再需要自己持有的对象时释放非自己持有的对象无法释放 ARC的具体实现编译期和运行期ARC做的事情ARC实现: __autoreleasing 与 Autoreleas…

铁电液晶破局 VR/AR:10000PPI 重构元宇宙显示体验

一、VR/AR 沉浸感困境&#xff1a;传统显示技术的天花板在哪&#xff1f; &#xff08;一&#xff09;纱窗效应与眩晕感&#xff1a;近眼显示的双重枷锁 当用户戴上 VR 头显&#xff0c;眼前像素网格形成的 “纱窗效应” 瞬间打破沉浸感。传统液晶 500-600PPI 的像素密度&…

竞争加剧,美团的战略升维:反内卷、科技与全球化

5月26日&#xff0c;美团发布2025年第一季度业绩报告&#xff0c;交出了一份兼具韧性与创新性的成绩单。 报告显示&#xff0c;公司一季度总营收866亿元&#xff0c;同比增长18%&#xff1b;核心本地商业收入643亿元&#xff0c;同比增长18%&#xff1b;季度研发投入58亿元&a…

(17)课36:窗口函数的例题:例三登录时间与连续三天登录,例四球员的进球时刻连续进球。

&#xff08;89&#xff09;例三登录时间 &#xff1a; 保留代码版本 &#xff1a; CREATE TABLE sql_8( user_id varchar(2), login_date date ); insert into sql_8(user_id,login_date) values(A,2024-09-02),(A,2024-09-03),(A,2024-09-04),(B,2023-11-25),(B,2023-12- 3…

高性能分布式消息队列系统(二)

上一篇博客将C进行实现消息队列的用到的核心技术以及环境配置进行了详细的说明&#xff0c;这一篇博客进行记录消息队列进行实现的核心模块的设计 五、项目的需求分析 5.1、项目框架的概念性理解 5.1.1、消息队列的设计和生产消费者模型的关系 在现代系统架构中&#xff0c;…

华为OD机试真题——天然蓄水库(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 2025华为OD真题目录+全流程解析/备考攻略/经验分享 华为OD机试真题《天然蓄水库》: 目录 题目…

【Harmony OS】数据存储

目录 数据存储概述 首选项数据存储 关系型数据库 数据存储概述 • 数据存储 是为了解决应用数据持久化问题&#xff0c;使得数据能够存储在外存中&#xff0c;达到保存或共享目的。 • 鸿蒙应用数据存储包括 本地数据存储 和 分布式数据存储 。 • 本地数据存储 为应用…

MybatisPlus--核心功能--service接口

Service接口 基本用法 MyBatisPlus同时也提供了service接口&#xff0c;继承后一些基础的增删改查的service代码&#xff0c;也不需要去书写。 接口名为Iservice&#xff0c;而Iservice也继承了IRepository&#xff0c;这里提供的方法跟BaseMapper相比只多不少&#xff0c;整…

uniapp调试,设置默认展示的toolbar内容

uniapp调试&#xff0c;设置默认展示的toolbar内容 设置pages.json中 pages数组中 json的顺序就可以只需要调整顺序&#xff0c;不会影响该bar在页面中的显示默认展示第一条page

笔记本电脑开机无线网卡自动禁用问题

1.问题环境 电脑品牌&#xff1a;华硕笔记本天选4 电脑型号&#xff1a;FX507VV 电脑系统&#xff1a;windows 11_x64_24h2 文档编写时间&#xff1a;2025年6月 2.问题现象 1. 笔记本电脑开机之后自动禁用无线网卡 使用USB转RJ45转接头同样无效&#xff0c;这个网卡也给禁…

推荐一款使用html开发桌面应用的工具——mixone

简介 mixone是开发桌面应用&#xff08;Win、Mac、Linux&#xff09;的一款工具、其基于electron实现。其拥有简单的工程结构。以为熟悉前端开发的程序员可以很轻松的开发出桌面应用&#xff0c;它比electron的其他框架更简单&#xff0c;因为那些框架基本上还需要了解electro…

【云原生开发】如何通过client-go来操作K8S集群

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

八.MySQL复合查询

一.基本查询回顾 分组统计 group by 函数作用示例语句说明count(*)统计记录条数select deptno, count(*) from emp group by deptno;每个部门有多少人&#xff1f;sum(sal)某字段求和select deptno, sum(sal) from emp group by deptno;每个部门总工资avg(sal)求平均值select…

FastMCP vs MCP:协议标准与实现框架的协同

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…

AI视频“入驻”手机,多模态成智能终端的新战场

文&#xff5c;乐乐 今天&#xff0c;无线蓝牙耳机&#xff08;TWS&#xff09;已经成为人人都用得起的产品。 但退回到9年前&#xff0c;苹果AirPods是全球第一款真正意义上的无线蓝牙耳机。靠着自研并申请专利的Snoop监听技术&#xff0c;苹果解决了蓝牙耳机左右延时和能耗…