字节 今日头条-C++ 二面
1. C++ 内存模型里,memory_order_relaxed/acquire/release/seq_cst 分别适合什么场景?
- relaxed:只保证原子性,不保证顺序;常用于统计计数器。
- acquire/release:成对使用,建立“happens-before”;适合发布-订阅模型。
- seq_cst:最强顺序一致性,最容易推理但性能可能较低。
典型场景:生产者写数据后 flag.store(true, release),消费者 if(flag.load(acquire)) 再读数据,保证读到完整写入结果。
2. 讲讲你如何设计一个“无锁队列”,以及 ABA 问题怎么处理?
无锁队列通常基于 CAS(compare_exchange)更新头尾指针。 核心难点:
- ABA(指针值看似没变但对象已变);
- 内存回收(节点被其他线程访问时不能提前 free)。
常见处理:
- ABA:版本号/tagged pointer;
- 内存回收:Hazard Pointer、Epoch Based Reclamation。
这题重点不是“写完代码”,而是你能说清楚正确性前提和工程代价。
3. shared_ptr 在高并发下的性能问题有哪些?你怎么优化?
问题主要是:
- 引用计数原子增减造成 cache line 抖动;
- 控制块额外分配;
- 频繁拷贝导致隐性开销。
优化手段:
- 默认优先 unique_ptr;
- 热路径减少 shared_ptr 传值,改 const& 或裸指针观察;
- make_shared 合并分配,减少碎片;
- 生命周期明确时改对象池/arena。
4. 你在 epoll 中怎么选 LT 和 ET?为什么 ET 更容易踩坑?
- LT(水平触发)简单稳妥:只要缓冲区还有数据就会继续通知;
- ET(边缘触发)性能潜力更高,但要求一次性读到 EAGAIN,否则会“丢事件感知”。
ET 踩坑点:
- 非阻塞没配全;
- 没循环 read/write 到 EAGAIN;
- 半包处理不完善。
5. 讲下你对零拷贝(zero-copy)的理解,sendfile 真的“零拷贝”吗?
“零拷贝”通常是减少用户态和内核态之间的数据拷贝,不是物理意义零移动。 sendfile 避免了“读到用户态再写回内核”的拷贝,降低 CPU 开销和上下文切换。 但在某些网卡/协议栈路径里仍可能有 DMA 或内核内部复制。 面试要点:说清“减少拷贝路径”而不是绝对化。
6. Reactor + 线程池架构里,如何避免任务队列堆积导致尾延迟恶化?
治理思路:
- 队列分级(高优先级请求单独队列);
- 背压(队列长度阈值触发限流/快速失败);
- 动态扩缩容 worker;
- 超时传播(上游超时预算传递到下游);
- 拆分慢任务(异步化)。
核心指标看 P99、队列等待时
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
C++ 常考面试题总结 文章被收录于专栏
本专栏系统梳理C++方向, 大中厂高频高频面试考点 , 内容皆来自真实面试经历,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力.