百度 C++软件开发 一面 面经

1. 进程和线程有什么区别?

  • 进程是操作系统资源分配的基本单位,拥有独立的地址空间、文件描述符、信号处理等资源
  • 线程是 CPU 调度的基本单位,共享所属进程的内存空间和资源,拥有独立的栈和寄存器状态
  • 创建和切换线程的开销远小于进程,线程间通信直接读写共享内存,进程间通信需要专门的 IPC 机制
  • 一个线程崩溃可能导致整个进程崩溃;一个进程崩溃不影响其他进程,隔离性更好
  • 多线程适合共享数据频繁的并发场景;多进程适合需要强隔离、稳定性要求高的场景

2. 为什么推荐用 make_shared 而不是直接 new 来构造 shared_ptr?

  • 直接 new 会进行两次内存分配:一次分配对象本身,一次分配控制块(引用计数);make_shared 只做一次内存分配,将对象和控制块放在同一块内存中,减少分配开销和内存碎片
  • 异常安全:shared_ptr<T>(new T(), deleter) 这种写法,如果构造函数和 shared_ptr 构造之间抛异常,可能导致内存泄漏;make_shared 不存在这个问题
  • 缓存友好:对象和控制块相邻,访问时更可能在同一缓存行

缺点:

  • make_shared 的内存只有在强引用和弱引用都归零后才释放,若存在大量 weak_ptr,对象销毁后内存仍被控制块占用,可能延迟内存释放

3. STL 迭代器失效在哪些场景下会发生?以 vector 为例

插入操作:

  • 在末尾 push_back 时,若触发扩容(重新分配内存),所有迭代器、指针、引用全部失效
  • 在中间 insert 时,插入位置之后的所有迭代器失效,若触发扩容则全部失效

删除操作:

  • erase 删除某个元素后,该位置及之后的所有迭代器失效,之前的迭代器仍然有效

正确做法:

  • erase 返回值是指向下一个有效元素的迭代器,删除时应使用返回值更新迭代器
  • 遍历时删除元素用 it = vec.erase(it) 而不是 vec.erase(it); it++
  • 其他容器:map/set 删除元素只失效被删除的迭代器;list 插入删除不影响其他迭代器

4. TCP 拥塞控制的机制是什么?

拥塞控制的目的是防止发送方发送过快导致网络拥塞,分四个阶段:

  • 慢启动:连接建立后拥塞窗口(cwnd)从 1 开始,每收到一个 ACK 翻倍增长,指数增长直到达到慢启动阈值(ssthresh)
  • 拥塞避免:cwnd 超过 ssthresh 后改为线性增长,每个 RTT 增加 1,避免增长过快
  • 快重传:收到 3 个重复 ACK 时立即重传丢失的包,不等超时,减少等待时间
  • 快恢复:快重传后将 ssthresh 设为当前 cwnd 的一半,cwnd 设为 ssthresh,继续拥塞避免而不是回到慢启动

发生超时时:ssthresh 减半,cwnd 重置为 1,重新进入慢启动,惩罚更重。

5. weak_ptr 除了解决循环引用,在 lambda 中如何安全访问可能已销毁的对象?

核心问题:lambda 捕获 shared_ptr 会延长对象生命周期;捕获裸指针或引用则对象销毁后访问是未定义行为。

正确做法是捕获 weak_ptr,在 lambda 内部 lock() 升级为 shared_ptr 再使用:

  • lock() 成功说明对象还存在,返回有效的 shared_ptr
  • lock() 返回空说明对象已销毁,直接返回不做任何操作
  • 这样 lambda 不会延长对象生命周期,也不会出现悬空指针访问

典型场景:异步回调、定时器回调中访问发起请求的对象,对象可能在回调触发前已经析构,用 weak_ptr 可以安全地处理这种情况。

6. TCP 如何实现可靠传输?

TCP 通过以下机制保证可靠性:

  • 序列号和确认号:每个字节都有序列号,接收方通过 ACK 确认收到的数据,发送方知道哪些数据已

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++八股文全集 文章被收录于专栏

本专栏系统梳理C++技术面试核心考点,涵盖语言基础、面向对象、内存管理、STL容器、模板编程及经典算法。从引用指针、虚函数表、智能指针等底层原理,到继承多态、运算符重载等OOP特性从const、static、inline等关键字辨析,到动态规划、KMP算法、并查集等手写实现。每个知识点以面试答题形式呈现,注重原理阐述而非冗长代码,帮助你快速构建完整知识体系,从容应对面试官提问,顺利拿下offer。

全部评论
问的还是比较基础的
点赞 回复 分享
发布于 03-19 11:49 四川

相关推荐

头像
04-20 22:26
南京大学 Java
攒人品ing~(一天三面我燃尽了)个人背景介绍一、&nbsp;项目深挖:高并发博客系统架构面试官提问:你的并发控制和API限流是怎么做的?面试官追问:点赞的接口限流具体怎么实现的?面试官追问:数据最终怎么落库?MQ消息丢了怎么办?二、&nbsp;场景题:使用Redis实现QPS/QPM/QPD限流面试官提问:如果要用Redis限制一个接口在滚动窗口下的QPS、QPM、QPD,怎么做?第一版思路:将时间单位拼接到Redis&nbsp;Key中。面试官指出:这会导致Key数量爆炸式增长。第二版思路:使用Hash结构,记录用户在特定时间窗口内的访问次数。面试官指出:这种方式只能记录自然时间(如自然天、自然秒),无法满足滑动窗口的需求。第三版思路:使用ZSet实现滑动窗口,Score设为时间戳,Value设为唯一标识。每次请求进来先移除时间窗口之前的数据,再使用&nbsp;`ZCARD`&nbsp;统计当前元素个数来判断是否限流。面试官指出:在QPD(每天调用量)极大且高频的场景下,ZSet会导致元素过多,产生大Key问题。第四版思路(最终被认可):针对精度要求没那么高的QPM/QPD,采用“分桶计数”思想。将一天24小时分为1440个分钟桶,使用String存计数值。每次判断时只需将最近时间段内的桶数据相加即可,旧桶设置自动过期销毁。表示该方案可行。三、&nbsp;项目深挖:缓存三大问题解决方案面试官提问:你在项目中提到的“布隆过滤器&nbsp;+&nbsp;互斥锁&nbsp;+&nbsp;逻辑过期”是怎么协同工作的?四、&nbsp;手撕算法题目:LeetCode&nbsp;124.&nbsp;二叉树中的最大路径和。五、&nbsp;反问环节问:入职后实习生的主要工作内容是什么?问:团队内部对于AI写代码的认可度如何?问:对我今天面试表现的评价和建议?
查看9道真题和解析
点赞 评论 收藏
分享
评论
1
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务