腾讯 C++ 一面

腾讯 · C++ 开发工程师 · 一面 · 2026-03

面试题目

一、自我介绍

  • 个人情况介绍

二、基础知识

  1. 多态的实现机制是什么?
  2. 如何保证并发安全?
  3. 了解 CAS 操作吗?
  4. CAS 有哪些问题?
  5. ABA 问题了解吗?
  6. 内核态和用户态的区别是什么?
  7. 协程有了解过吗?
  8. HTTP、TCP、UDP 分别是什么,有什么区别?
  9. TCP 用什么机制保证可靠交付?
  10. HTTP 可以基于 UDP 实现吗?
  11. UDP 为什么可以用在游戏传输中?

三、项目拷打

  1. 缓存系统是本地的吗?怎么实现的?
  2. LRU 怎么实现?
  3. LRU-K 相比 LRU 的进阶在哪里?
  4. 内存泄露怎么解决?
  5. 了解垃圾回收吗?C++ 为何不做自动 GC?
  6. shared_ptr 的引用计数原理是什么?什么时候被清理?
  7. 工作负载剧烈变化的场景是怎么个变化?(项目细节)
  8. 如果缓存系统加上 TTL,你怎么实现?
  9. Redis 的 LRU 策略了解吗?
  10. 缓存击穿是什么?解决方案有哪些?
  11. QPS 怎么测的?在什么环境下测量的?
  12. 测 QPS 需要考虑哪些指标?比如 CPU 核数?
  13. 哈希倾斜了解吗?分片时出现哈希倾斜怎么解决?
  14. Raft 从哪里学习的?
  15. MCP 了解吗?SKILL 了解吗?
  16. 了解哪些分布式一致性算法(Raft、ZAB 等)?
  17. 哪些场景需要分布式一致性协议?
  18. Protobuf 和 JSON 在网络传输中怎么抉择?
  19. CAP 中的一致性和数据库事务的一致性有何区别?
  20. CAP 的 CA、CP、AP 各自是什么?有哪些代表协议?分别用在哪些场景?

四、学习与成长

  • 平时如何学习?当前的学习安排是什么?

五、算法题

  1. LeetCode 19:删除链表的倒数第 N 个结点

    • 说了思路,面试官追问:可以类比哪种数据结构解决?(答:栈)
  2. LeetCode 402:移掉 K 位数字

    • 手写,耗时约 15 分钟,部分细节未考虑周全

六、反问环节

  1. 业务范围是什么?
  2. 面试官反馈:基础扎实,但项目细节还需深挖。

参考解析

多态的实现机制

  • 静态多态:函数重载,编译期决议,通过函数签名区分。
  • 动态多态:虚函数 + 虚函数表(vtable)。每个含虚函数的类有一张 vtable,每个对象头部有虚函数指针(vptr)指向该表。运行时通过 vptr 查表调用实际函数,实现派生类覆盖基类行为。

CAS 与 ABA 问题

  • CAS(Compare And Swap):原子地比较内存值与期望值,相等则替换为新值,否则失败重试(自旋)。不陷入内核,适合低竞争场景;高竞争时 CPU 忙等待浪费资源。
  • ABA 问题:线程 A 读值为 A,期间线程 B 将值改为 B 再改回 A,线程 A 的 CAS 成功但逻辑可能错误。
    解法:引入版本号/时间戳,每次修改递增版本,比较时同时校验版本(如 AtomicStampedReference)。

TCP 可靠交付机制

  • 序列号 + ACK:接收方确认收到的字节范围。
  • 超时重传:未收到 ACK 则重传,支持快速重传(收到 3 个重复 ACK)。
  • 流量控制:接收窗口(rwnd)告知发送方可接收的数据量。
  • 拥塞控制:慢启动、拥塞避免、快恢复,防止网络过载。

LRU 与 LRU-K 实现

  • LRU:哈希表 + 双向链表,O(1) 查找与插入。访问时将节点移到链表头,淘汰时删除链表尾。
  • LRU-K:数据需被访问 K 次才进入主缓存,冷数据放历史队列,防止偶发性大扫描污染热数据,提升缓存命中率。

shared_ptr 引用计数原理

  • 内部维护一个控制块,包含强引用计数和弱引用计数。拷贝时强引用计数 +1,析构时 -1。
  • 强引用计数归零时销毁所指对象;弱引用计数也归零时销毁控制块本身。
  • 注意:循环引用会导致引用计数永不归零,用 weak_ptr 打破循环。

缓存击穿与解决方案

  • 缓存击穿:热点 key 过期瞬间,大量请求同时穿透缓存打到数据库。
  • 解法:① 互斥锁(只允许一个线程回源,其余等待);② 逻辑过期(不设物理 TTL,由业务层判断并异步更新);③ 提前续期(后台定时刷新热点 key)。

CAP 理论

  • C(一致性):所有节点同时看到相同数据(注意:不同于事务 ACID 中的一致性,后者指业务约束不被破坏)。
  • A(可用性):每个请求都能收到响应(不保证最新数据)。
  • P(分区容忍性):网络分区时系统仍可运行。
  • CP:ZooKeeper、Raft(etcd),牺牲可用性保证一致性,适合配置中心、分布式锁。
  • AP:Cassandra、Eureka,牺牲一致性保证可用性,适合购物车、DNS。
  • CA:单机关系型数据库(不具备分区容忍,实际分布式系统必须选 P)。

Protobuf vs JSON

  • Protobuf:二进制编码,体积小(约 JSON 的 1/3~1/5),序列化/反序列化速度快,但可读性差,需要 .proto 文件,适合高吞吐内部服务通信。
  • JSON:文本格式,可读性好,生态广泛,适合对外 API、调试场景及跨语言兼容要求高的场合。

LeetCode 402:移掉 K 位数字(贪心 + 单调栈)

  • 维护一个单调递增栈,遍历每位数字:若当前数字小于栈顶且还能删除(k > 0),则弹出栈顶(k—),将当前数字入栈。
  • 遍历结束后若 k > 0,从栈尾再删 k 个。
  • 去掉结果的前导零,若为空则返回 "0"
  • 关键细节:前导零处理、k 用完后直接追加剩余数字、结果为空时返回 "0"