校招 未知部门 / 后端-C++ / 一面

[面试日期] 2026-09-10 [面试时长] 未知
[学校背景] 浙江大学 | 985 [学历背景] 未知
[发布人] 面试之星官方收录
<h2>快手C++一面面经</h2> <h1>1. 做个简单自我介绍,并说明为什么投快手 C++ 方向?</h1> <ol> <li>我是 XX 学校计算机相关专业,主攻 C++ 后端 / 基础架构,常用技术栈包括 Linux、多线程、网络编程和常用中间件。</li> <li>实习期间主要做高并发链路里的服务性能优化和稳定性治理,熟悉从协议解析到落库的完整路径。</li> <li>投快手是因为业务体量大、对性能和稳定性要求高,C++ 岗位更能把底层能力用起来。</li> <li>个人更擅长把问题拆到 CPU、内存、锁和 IO 层面定位,也希望在真实大流量场景里继续深挖。</li> </ol> <h1>2. 实习项目里,为什么消息分发不用无锁队列,而是加了分片锁?</h1> <ol> <li>无锁队列在单生产者单消费者场景很合适,但我们是多生产者多消费者,CAS 冲突会很明显。</li> <li>全局限流和无锁结构叠在一起后,伪共享和重试成本上升,吞吐反而掉。</li> <li>改成按 key 分片加细粒度锁后,热点被打散,临界区更短,毛刺更可控。</li> <li>同时用线程本地缓冲批量提交,减少锁竞争次数。</li> <li>最终在同等 CPU 下,尾延迟更稳,也更容易做监控和故障隔离。</li> </ol> <h1>3. 了解跳表吗?为什么 Redis 的有序集合会用跳表而不是纯红黑树?</h1> <ol> <li>跳表是多层链表,上层是下层的“快速索引”,期望查找、插入、删除都是对数复杂度。</li> <li>实现上每个节点按概率晋升层高,通过空间换取更简单的区间遍历。</li> <li>相对红黑树,跳表实现更直观,范围查询、按排名取数据更自然。</li> <li>Redis 还结合哈希表做成员定位,跳表负责有序遍历和范围操作。</li> <li>工程上跳表局部性也不错,对高并发下的维护成本更友好。</li> </ol> <h1>4. <code>std::unordered_map</code> 底层怎么组织?什么时候会 rehash?最坏复杂度怎么来的?</h1> <ol> <li>底层通常是哈希桶加链表或等效冲突链,C++ 标准保证平均常数复杂度,不强制具体开链细节。</li> <li>负载因子过高时触发 rehash,把元素迁移到更大的桶数组。</li> <li>若哈希函数质量差,大量 key 撞到同一桶,退化成长链,查找接近线性。</li> <li>迭代器和引用在 rehash 后可能失效,业务里不能假设指针一直有效。</li> <li>高并发下标准库 <code>unordered_map</code> 本身不是线程安全的,读写并发要外部同步或换并发容器方案。</li> </ol> <h1>5. C++ 里 <code>thread_local</code> 变量生命周期怎么理解?什么场景会把内存“挂住”?</h1> <ol> <li><code>thread_local</code> 对象按线程创建,线程结束时销毁,不是进程级全局一份。</li> <li>如果 <code>thread_local</code> 里缓存了大块 buffer、连接、句柄,线程长期不退出,内存就会一直占用。</li> <li>线程池场景尤其常见:线程复用导致 TLS 对象只增不减,看起来像泄漏。</li> <li>规避方式是控制缓存上限、定期收缩,或在任务边界主动释放重资源。</li> <li>也不要在 TLS 里存放跨线程共享且需要复杂所有权管理的对象,职责边界会乱。</li> </ol> <h1>6. 讲一下进程虚拟地址空间布局,以及 <code>new</code> 失败时你怎么处理?</h1> <ol> <li>常见布局包括代码段、只读数据、可读写数据、堆、内存映射区、栈,</li> </ol>
AI 推荐面试题