C++权威八股文总结:面试高频知识点一次讲透
面试里问 C++,从来不是在考你会不会写个 for 循环,也不是只想听你背“封装、继承、多态”。真正想看的,是你对 对象模型、生命周期、资源管理、泛型能力、STL 使用习惯、现代 C++ 语义 到底理解到什么程度。
先说结论:C++ 八股的核心,不是零散知识点,而是四条主线。
- 对象是怎么创建、销毁、布局和调用的
- 资源是怎么管理的,尤其是内存、所有权、拷贝与移动
- 泛型和 STL 是怎么帮你写出更安全、更高效代码的
- 现代 C++ 语义你到底是“听过”,还是“真的会用”
一、对象模型:C++ 的根基在这里
C++ 和很多语言最大的区别之一,就是它离内存和对象布局非常近。
面试里这里常问的,不是“类是什么”,而是:
- 对象在内存里怎么放
- 成员变量和成员函数分别属于什么
this指针是什么- 虚函数、多态到底怎么实现
- 构造、析构、拷贝、移动这些操作什么时候发生
最基本的结论要先记住:
- 成员变量属于对象
- 成员函数不属于某个对象实例本身,代码段里只有一份
- 非静态成员函数调用时默认带一个
this指针 - 静态成员变量属于类,不属于某个对象
- 静态成员函数没有
this指针
如果连这条线都不清楚,后面很多题会越答越虚。
核心大厂开发面试题以及基础八股文资料汇总:
https://www.nowcoder.com/creation/manager/columnDetail/Mq7XWW
二、构造、析构、拷贝、移动:生命周期问题是高频核心
C++ 面试非常喜欢围绕对象生命周期追问,因为这直接决定你会不会写出有 bug 的代码。
这里最重要的是四组概念:
- 构造函数和析构函数
- 拷贝构造和拷贝赋值
- 移动构造和移动赋值
- Rule of Three / Five / Zero
1. 构造和析构
构造函数负责对象初始化,析构函数负责对象销毁时释放资源。
如果类里持有堆内存、文件句柄、锁、socket 这类资源,析构函数就不能乱写。
要点:
- 构造函数可以重载,析构函数不能重载
- 析构函数一般不能带参数
- 基类析构函数如果可能通过基类指针删除子类对象,必须写成虚析构函数
这句是面试里的标准送分点:
“多态基类通常要有虚析构函数,否则通过基类指针释放派生类对象会导致析构不完整。”
2. 拷贝语义
拷贝构造发生在“用一个已有对象初始化另一个对象”时。
拷贝赋值发生在“两个已经存在的对象之间赋值”时。
最常考的坑是浅拷贝和深拷贝。
如果类内部直接管理裸指针,那么默认拷贝往往只是地址复制,多个对象会指向同一块内存,最终导致:
- 重复释放
- 悬空指针
- 数据互相污染
所以一旦类自己管理资源,就必须认真考虑拷贝行为。
3. 移动语义
C++11 之后,移动语义几乎是必考点。
它解决的问题很明确:
有些对象不需要真的“复制资源”,只需要把资源所有权转走。
典型场景:
- 返回大对象
- 容器扩容搬迁元素
- 临时对象传递
- 智能指针转移所有权
这里最关键的几个点:
- 左值有名字、可取地址、可重复使用
- 右值通常是临时对象,适合“被搬走”
std::move本身不移动,它只是把对象转换成右值引用- 真正发生移动的是移动构造或移动赋值函数
面试如果问“移动语义的意义”,一个很稳的回答是:
减少不必要的深拷贝,提高性能,同时让资源所有权转移更明确。
三、引用、指针、const:这是基本功,不是小题
这一块几乎每场 C++ 面试都会问。
1. 引用和指针的区别
你至少要说清这些:
- 引用必须初始化,指针不一定
- 引用一旦绑定,通常不能改绑
- 指针是变量,存地址;引用更像别名
- 指针可以为
nullptr,引用通常不允许为空语义
但真正加分的,不是背这些差异,而是知道什么时候用谁。
一般来说:
- 参数传递优先考虑
const T& - 需要表达“可为空”时更适合指针
- 需要表达“对象别名、必然存在”时更适合引用
2. const 的常见考法
const 高频得不能再高频了,常见问题包括:
const int *pint * const pconst int * const pconst修饰成员函数是什么意思const对象能调用哪些成员函数
一句话记忆:
const修饰谁,谁就不能通过这个名字被改const成员函数表示不修改对象的逻辑状态mutable可以突破这种只读限制,用于缓存等场景
四、虚函数、多态、vptr/vtable:面试最爱深挖的地方
如果说 C++ 面试最能区分“会背”和“真懂”的地方,虚函数绝对排前列。
1. 多态的本质
多态分静态多态和动态多态。
- 静态多态:函数重载、模板
- 动态多态:虚函数 + 继承 + 基类指针/引用调用
动态多态成立的条件要说全:
- 要有继承关系
- 基类函数要声明为
virtual - 必须通过基类指针或引用调用重写后的函数
2. 虚函数如何实现
核心点:
- 含虚函数的类通常会有虚函数表
vtable - 对象里通常会有虚表指针
vptr - 运行时通过
vptr找到实际类型对应的虚函数表,从而调用正确函数
这就是“动态绑定”的本质。
3. 纯虚函数和抽象类
- 纯虚函数写法:
virtual void func() = 0; - 含纯虚函数的类是抽象类,不能实例化
- 派生类如果不重写纯虚函数,自己也还是抽象类
这类题不难,但很高频。
五、new/delete、malloc/free、智能指针:资源管理是现代 C++ 面试重点
1. new/delete 和 malloc/free 的区别
标准回答至少包括:
new/delete是 C++ 运算符,malloc/free是 C 库函数new会调用构造函数,delete会调用析构函数malloc只分配原始内存,free只释放原始内存new返回对应类型指针,malloc返回void*
真正的面试意图其实是看你有没有资源管理意识。
现代 C++ 项目里,能不用裸 new 就尽量不用。
2. 智能指针
这是现代 C++ 面试的重点区。
最常见三个:
std::unique_ptrstd::shared_ptrstd::weak_ptr
要点非常清楚:
unique_ptr独占所有权,不能拷贝,可以移动shared_ptr引用计数,共享所有权weak_ptr不增加引用计数,用来观察资源,常用于打破循环引用
高频追问:
shared_ptr为什么会有循环引用问题make_shared和直接new有什么差异unique_ptr为什么更轻量- 智能指针能不能完全替代裸指针
一句话总结这部分最容易得分:
现代 C++ 的核心思想之一,就是把资源管理从“人肉记忆”变成“对象生命周期自动托管”。
六、STL 必须会,但不能只会名字
很多人 STL 只会背 vector/list/map/unordered_map 的区别,这肯定不够。
面试真正常问的是:
- 底层数据结构
- 插入删除查找复杂度
- 迭代器失效
- 什么时候选哪个容器
1. vector
高频中的高频:
- 底层连续内存
- 支持随机访问
- 尾插效率高
- 中间插入删除可能搬移大量元素
- 扩容会引发重新分配,迭代器、指针、引用可能失效
2. list
- 双向链表
- 任意位置插入删除方便
- 不支持随机访问
- 节点分散,缓存局部性差
3. map 和 unordered_map
map通常基于红黑树,有序,复杂度稳定unordered_map基于哈希表,无序,平均查找快,但最坏可能退化
真正面试里不要只说“一个有序一个无序”,太薄了。
七、模板、泛型、inline、constexpr:现代 C++ 语义不能缺
1. 模板
模板的核心价值不是“少写代码”,而是 把算法和类型解耦。
高频点:
- 函数模板和类模板
- 模板实例化
- 模板特化与偏特化
- 为什么模板实现通常放头文件
最后一个很常问,答案是:
模板需要在编译期看到完整定义,才能完成实例化。
2. inline
inline 现在不只是“建议内联展开”,更重要的一层意义是:
- 允许函数在多个翻译单元中定义而不违反 ODR
- 类内定义成员函数通常隐式具备 inline 属性
3. constexpr
constexpr 是现代 C++ 面试里越来越常见的点。
你至少要知道:
- 它强调编译期可求值
- 可用于常量表达式、编译期优化
- 比传统宏和
const更类型安全、更现代
八、多线程基础:不会太深,但越来越常问
如果岗位偏后端、客户端、基础架构,C++ 并发几乎绕不过。即使是嵌入式 Linux 岗,也常会问到。
高频点包括:
threadmutexlock_guardunique_lockcondition_variableatomic
这里面最容易被追问的是:
- 为什么会有竞态条件
- 互斥锁和原子操作的区别
- 死锁怎么产生,怎么避免
lock_guard和unique_lock的区别
不用一上来讲内存序讲到飞起,但基本概念一定要稳。
九、面试中什么算“会 C++”,什么不算
如果你想知道面试官怎么看“C++ 基础扎实”,标准通常不是你背了多少定义,而是下面这几件事。
算会的表现:
- 能把对象生命周期讲清楚
- 能解释拷贝、移动、所有权
- 知道虚函数、多态背后的运行机制
- 能说清 STL 容器选型依据
- 知道现代 C++ 为什么提倡 RAII 和智能指针
- 遇到问题会从语义、性能、资源、安全性一起分析
不算会的表现:
- 只会背“封装继承多态”
- 只会说“智能指针防内存泄漏”
- 只会说“vector 底层是数组”
- 分不清拷贝构造和赋值
- 分不清左值右值、移动和转发
- 说不清为什么基类析构要设为虚函数
十、适合面试前突击的高频题清单
- C 和 C++ 最核心的区别是什么
- 引用和指针的区别是什么
const有哪些典型用法static在 C++ 中有哪些作用this指针是什么- 构造函数能不能是虚函数
- 析构函数为什么常常要写成虚函数
- 拷贝构造和拷贝赋值的区别是什么
- 什么是深拷贝,什么是浅拷贝
- 什么是移动语义
std::move到底做了什么- 左值、右值、右值引用怎么理解
- 什么是完美转发
- 虚函数是怎么实现动态多态的
- 纯虚函数和抽象类是什么
new/delete和malloc/free的区别是什么unique_ptr、shared_ptr、weak_ptr的区别是什么shared_ptr为什么会循环引用vector扩容会发生什么- 哪些容器会发生迭代器失效
map和unordered_map如何选择- 模板为什么通常写在头文件里
inline和constexpr分别解决什么问题mutex和atomic的适用场景有什么不同- RAII 为什么是现代 C++ 的核心思想之一
结尾
C++ 八股真正难的地方,从来不是知识点多,而是它每一个点都能往下深挖,而且彼此之间是连着的。你要是真的想把 C++ 面试准备到位,不要只背单题,而要围绕这几条主线去复习:对象模型、生命周期、资源管理、泛型与 STL、现代语义。
把这几条线吃透,很多题你不用死记,也能自己顺着逻辑答出来。
