C++ 常考面试题总结(附复习思路)
前言
C++ 这门语言,在开发岗位里一直都挺特殊的。
一方面,它历史足够久,语法特性很多,往深了问几乎问不完;另一方面,它又一直活跃在高性能开发的一线,不管是后端、客户端、音视频、游戏、基础架构,还是嵌入式方向,很多岗位都会明确要求有 C++ 基础。
所以面试里,C++ 基本属于绕不过去的一块。
而且 C++ 面试有个很明显的特点:不太容易只停留在表面。很多问题看起来像基础题,但只要面试官愿意追问,很快就会从语法问到原理,从原理问到工程实践。
比如:
- 为什么基类析构函数通常要写成虚函数?
vector和list到底怎么选?shared_ptr为什么会有循环引用问题?- 右值引用到底解决了什么问题?
- 多线程里加了锁,为什么性能还是可能很差?
这些问题如果只是背过概念,往往不太够。真正到面试里,还是得看能不能把东西讲明白。
这篇文章就简单整理一版 C++ 面试里比较常见的 20 个问题,只列问题,适合面试前过一遍。后面再补一下我比较建议的准备思路,方便复习的时候抓重点。
一、C++ 常见面试题
基础语法
- C++ 里指针和引用有什么区别?
const在 C++ 中有哪些常见用法?static关键字在不同场景下分别有什么作用?#define、const、inline之间有什么区别?- 函数重载、重写、隐藏分别是什么意思?
类与对象
class和struct在 C++ 里的区别是什么?- 什么是封装、继承、多态?C++ 是怎么支持多态的?
- 什么是虚函数、纯虚函数、虚析构函数?
- 构造函数、析构函数、拷贝构造函数、移动构造函数分别在什么情况下调用?
- C++ 对象模型里,虚函数表是怎么工作的?
内存管理
- 栈上对象和堆上对象有什么区别?
new/delete和malloc/free有什么区别?- 什么是内存泄漏?常见原因有哪些?怎么排查?
- 什么是 RAII?为什么 C++ 很强调这个思想?
unique_ptr、shared_ptr、weak_ptr的区别和使用场景是什么?
现代 C++ / STL / 并发
- 什么是左值、右值、右值引用?移动语义解决了什么问题?
std::move和std::forward的区别是什么?- 模板的本质是什么?模板实例化发生在什么时候?
vector、list、deque、map、unordered_map这些常用容器怎么选?- C++ 多线程里常见的同步方式有哪些?互斥锁、条件变量、原子变量分别适合什么场景?
如果你也面试C++不妨看看我的专栏: C++常考面试题总结
二、C++ 面试前怎么准备会更有效
很多人准备 C++ 面试的时候,容易一上来就开始背题。但说实话,C++ 的点太碎了,单纯按题目去背,背到后面很容易乱。
我自己的建议是,最好按模块去准备。
1. 先把主干知识捋顺
C++ 面试里高频的内容,大致就这几块:
- 基础语法
- 类和对象
- 内存管理
- STL 容器
- 智能指针
- 模板
- C++11 之后的新特性
- 多线程和并发
先把这些主干内容分清楚,再去看具体问题,会轻松很多。
比如在看智能指针的时候,就可以顺便把 RAII、资源管理、析构函数、异常安全这些内容一起串起来。看多态的时候,也可以顺带把虚函数表、虚析构、对象模型这些内容一起补上。
这样复习怎么也比“今天背 50 道题”更稳。
2. 不要只记结论,尽量往下多想一层
C++ 面试很容易考“为什么”。
像下面这些题,如果只是会背一句话,其实很容易被继续追问:
- 为什么
vector插入尾部快? - 为什么
list不一定比vector更适合频繁插入删除? - 为什么
shared_ptr有性能开销? - 为什么移动语义可以减少拷贝?
- 为什么基类析构函数不写成虚函数会有问题?
所以很多知识点,最好别只停留在“是什么”,而是尽量把下面几层也想明白:
- 它解决了什么问题?
- 它是怎么实现的?
- 它有什么好处?
- 它有没有副作用或者使用成本?
这样在面试里回答出来,会明显比单纯背定义更像“真懂”。
3. 一定要能和项目联系起来
这一点挺重要的。
很多人八股背得不少,但一问项目就说不出来。面试官其实也很关心:学这些东西,到底有没有在实际开发里用过。
所以建议准备的时候,顺手把自己项目里和 C++ 有关的内容也整理一下,比如:
- 项目里主要用了哪些 STL 容器?
- 为什么这里选
vector,那里选unordered_map? - 有没有用到智能指针?
- 有没有遇到过内存泄漏、野指针、崩溃问题?
- 有没有做过性能优化?
- 有没有写过多线程代码?怎么做同步的?
- 有没有踩过锁竞争、死锁、线程安全之类的坑?
很多时候,同一个问题,只讲理论和“理论 + 项目例子”,给人的感觉是完全不一样的。
4. STL 和现代 C++ 基本是重点
这几年面试里,传统语法当然还会问,但现代 C++ 的比重确实越来越高了。
像下面这些内容,出现频率都不低:
autonullptroverride- 右值引用
- 移动语义
- 完美转发
- lambda
- 智能指针
emplace_backunordered_mapthreadmutexatomic
尤其 STL,几乎是必问的。
至少得把几个常用容器的特点和适用场景说清楚,不然面试官很容易顺着往下问。比如
vector为什么这么常用?list的优缺点是什么?map和unordered_map怎么选?- 哪些操作会导致迭代器失效?
- 提前
reserve有什么意义?
这些都属于很常见的问题。
5. 并发这块,最好单独过一遍
如果投的是后端、高性能、基础架构这类岗位,那并发题基本是跑不掉的
常见内容一般包括:
- 线程和线程同步
- 互斥锁
- 条件变量
- 原子类型
- 死锁
- 竞态条件
- 伪共享
- 内存模型
- 线程池
这一块很多人平时也许用过 mutex,但不一定真的理解得比较完整。面试官如果继续问:
- 条件变量为什么要搭配谓词使用?
- 原子操作能不能完全替代锁?
- 为什么会有伪共享?
- 线程池一般要考虑哪些问题?
如果没提前整理过,临场容易有点乱。
所以这一块建议最好单独做一轮专题复习,不然挺容易吃亏。
6. 有时间的话,适当看一点源码
这个不一定非要啃特别深,但确实挺有帮助。
比如去看看这些内容的简单实现或者源码思路:
vectorstringshared_ptrunordered_map- 简单线程池
看完之后,很多原来抽象的点会变得具体很多。不一定要把每一行代码都记住,但至少要知道:
- 它底层大概是什么结构
- 它为什么这样设计
- 它这样设计的代价是什么
面试里如果问到原理,回答起来会自然很多。
7. 最后一定要练口头表达
这个是很多人最容易忽略的。
平时自己看题的时候,常常会觉得“这个我会”。但真正到了面试现场,要求两分钟内把一个问题讲清楚,很多人就开始卡壳。
所以建议在复习的时候,最好自己开口说一说。哪怕是对着手机录音,或者对着文档自言自语,也比只看不说强。
回答问题的时候,可以尽量按这个顺序来:
- 先说定义
- 再说原理
- 再说适用场景
- 最后补一句常见坑或者注意点
这样的回答会显得更完整,也更有层次。
三、面试前建议重点看的内容
如果时间有限,我觉得可以优先看这些:
第一梯队
- 指针、引用、
const - 类、继承、多态、虚函数
- 栈和堆、内存泄漏
- RAII 和智能指针
- STL 常用容器
- 左值右值、移动语义
第二梯队
new/delete和malloc/free- 模板基础
- 迭代器失效
map和unordered_map- 锁、条件变量、原子操作
第三梯队
- 对象模型和虚函数表
- 内存模型
- 伪共享
- 线程池设计
- 崩溃定位、性能分析
如果是校招或者实习,前两部分基本就够用了。如果是社招或者 C++ 开发岗,第三部分最好也补一下。
结语
C++ 面试难的地方,其实不一定是题有多偏,而是它特别容易从一个基础问题一路追问到底。
以为只是问个语法,结果可能最后问到:
- 底层实现
- 内存布局
- 性能影响
- 工程实践
- 项目经验
所以准备 C++ 面试,最好的方式还是两步:
- 一步是把常见知识点系统过一遍
- 一步是把这些知识点和自己的项目经验连起来
这样面试的时候,才不会只剩下“背过一点印象”,而是真的能把问题答完整。
查看13道真题和解析