很多人背 C++ 八股,背到最后有一种错觉:好像每个问题都见过,但一到面试现场,面试官稍微换个问法,人就开始乱。
比如他不是直接问你“堆和栈的区别”,而是问你:“一个局部对象什么时候析构?返回局部对象为什么有时候没出问题?new 出来的内存为什么容易泄漏?”
你会发现,真正难的不是有没有背过,而是这些知识点能不能串起来。
先说结论:C++ 八股高频内容其实非常集中,反复考的无非就是对象模型、内存管理、拷贝控制、多态、模板/STL、智能指针、多线程这几块。面试官也不是要你把标准全文背下来,他更在意两件事:
第一,你是不是知道这个机制解决什么问题;
第二,你能不能说出它的代价、边界和常见坑。
一、C++八股到底在考什么
C++ 面试不是在考“你记不记得定义”,而是在考“你写代码时会不会踩坑”。
所以同一个知识点,面试通常有三层:
第一层,定义层。
比如什么是多态、什么是虚函数、什么是深拷贝和浅拷贝。
第二层,机制层。
比如虚函数表大概怎么工作的,为什么有虚函数就能动态绑定,为什么浅拷贝会出双重释放。
第三层,工程层。
比如什么时候应该禁用拷贝,什么时候该用移动语义,vector 扩容为什么会影响迭代器,智能指针为什么也能造成内存泄漏。
真正能拉开差距的,往往是后两层。
核心大厂开发面试题以及基础八股文资料汇总:
https://www.nowcoder.com/creation/manager/columnDetail/Mq7XWW
二、基础语法和对象模型
1. C 和 C++ 最核心的区别是什么
别答一堆“面向对象、封装继承多态”就完了。
更像样的回答应该是:C++ 在 C 的基础上引入了更完整的抽象机制和资源管理模型,比如类、构造析构、模板、重载、RAII、泛型和标准库,所以它不只是“语法更复杂的 C”,而是更强调类型系统和对象生命周期管理。
2. 什么是封装、继承、多态
这是最基础的八股,但经常是连环追问入口。
封装:把数据和操作封在一起,控制访问权限。
继承:复用已有类的接口和实现。
多态:同一接口在不同对象上表现不同行为,重点是运行时多态通常依赖虚函数。
3. struct 和 class 的区别
最常见答案:默认访问权限不同,struct 默认是 public,class 默认是 private。
如果再往前一步,可以补一句:在 C++ 里两者本质能力差别不大,更多是编码风格和语义表达上的区别。
4. 空类占多少字节
通常是 1 字节。
原因不是它真有成员,而是为了保证每个对象在内存中有独立地址。
三、内存管理是绝对高频
1. 堆和栈的区别
这是经典题,但别只答“栈快堆慢”。
更完整一点:
- 栈由编译器自动管理,存局部变量、函数参数等
- 堆由程序员手动申请释放,或通过 RAII/智能指针间接管理
- 栈空间通常较小,但分配释放快
- 堆空间更灵活,但容易产生碎片、泄漏和悬空指针
2. new/delete 和 malloc/free 的区别
高频到不能再高频。
核心点:
malloc/free是 C 的库函数,只负责内存分配和释放new/delete是 C++ 运算符,除了分配内存,还会调用构造/析构函数- 对于对象,尤其是有资源管理逻辑的对象,应该优先用
new/delete new[]和delete[]必须配对,否则析构行为可能出问题
3. 什么是内存泄漏
申请了内存但失去了访问它的方式,最终没有释放。
常见场景:
new后忘记delete- 异常路径提前返回
- 多个分支中只释放了部分资源
- 智能指针循环引用
4. 什么是野指针和悬空指针
野指针:没有初始化就乱指。
悬空指针:原来指向的对象已经释放,但指针还在。
工程里后者更常见,也更危险。
四、引用、指针、const、static,面试特别爱问
1. 指针和引用的区别
高频必背题。
简版答案:
- 指针本身是变量,有自己的地址,可以为空,可以改指向
- 引用本质上是别名,定义时必须初始化,通常不能重新绑定
- 语法上引用更像对象本身,使用更自然
- 指针更灵活,适合表达“可空”“可变指向”等语义
2. const 的作用
别只说“防止修改”。
常见考法:
const int *p:指向常量的指针,不能通过p改值int *const p:常量指针,p自己不能改指向const int *const p:两者都不能改
再往深一点,const 的意义是表达只读语义,增强接口约束,也方便编译器优化。
3. static 有哪些用法
这个题特别容易答散。
直接分三种:
- 局部
static:生命周期延长到程序结束,但作用域仍在局部 - 全局
static:限制链接范围,只在当前文件可见 - 类内
static成员:属于类而不是对象,所有对象共享
4. define 和 const 的区别
define是预处理替换,没有类型检查const是有类型的常量,作用域明确,更安全- 调试和编译期检查上,
const通常优于宏常量
五、拷贝控制、深浅拷贝、右值语义,常被一套连问
1. 深拷贝和浅拷贝
浅拷贝只是复制值本身,如果成员里有指针,就可能两个对象指向同一块资源。
深拷贝会复制资源本体,避免共享同一块动态内存。
为什么这题重要?
因为如果类自己管理堆资源,而你只用了默认拷贝构造和赋值,几乎就等着出双重释放。
2. 拷贝构造函数和赋值运算符区别
- 拷贝构造:用一个已有对象初始化新对象
- 赋值运算符:两个已存在对象之间赋值
这是两个完全不同的时机,很多人这里会混。
3. 为什么会有移动语义
因为有些对象管理的资源很重,拷贝代价高。
移动语义允许“资源所有权转移”,避免不必要的深拷贝,提高性能。
4. 左值和右值是什么
面试不要求你背标准定义,但要知道:
- 左值通常有名字、可取地址、可持久存在
- 右值通常是临时对象、字面量或即将销毁的值
T&&能绑定右值,是移动语义和完美转发的重要基础
六、多态、虚函数、继承,这一块最容易被追问
1. 什么是虚函数
用 virtual 修饰的成员函数,允许子类重写,并通过基类指针或引用在运行时动态绑定。
2. 什么是多态
最常考的是运行时多态:
父类指针/引用指向子类对象,调用虚函数时表现出子类行为。
3. 虚函数表是怎么回事
不要求你讲到 ABI 细节,但起码知道:
编译器通常会为有虚函数的类维护一张虚函数表,对象里有个指向这张表的指针。调用虚函数时通过它做动态分派。
4. 为什么析构函数常常要写成虚函数
如果基类指针指向派生类对象,而基类析构不是虚函数,delete 基类指针时可能只调用基类析构,导致派生类资源没释放完整。
这题是高频陷阱题。只要涉及“多态基类”,析构通常就该是虚的。
5. 纯虚函数和抽象类
- 纯虚函数写法:
virtual void f() = 0; - 含有纯虚函数的类叫抽象类,不能实例化
- 常用来定义接口规范
七、STL 和容器,不会真不太行
1. vector 和 list 的区别
别背“数组 vs 链表”就结束。
核心对比:
vector连续存储,随机访问快,尾插效率高list非连续存储,插删节点方便,但缓存命中差,随机访问不行- 实际工程里,
vector使用频率通常远高于list
2. vector 扩容会发生什么
这是很爱考的一题。
要点:
- 容量不够时会申请更大内存
- 原有元素会被拷贝或移动到新空间
- 旧空间释放
- 原有迭代器、指针、引用可能失效
3. map 和 unordered_map 的区别
map一般基于红黑树,元素有序,查找插入删除通常是O(logn)unordered_map基于哈希表,平均O(1),但最坏可能退化unordered_map不保证顺序,且依赖哈希函数和冲突处理
4. vector 和 deque 的区别
vector连续存储,尾部操作友好deque支持头尾高效插入删除,但内存不完全连续- 如果频繁头插头删,
deque更合适
八、智能指针,基本已经成默认高频题了
1. 为什么要有智能指针
为了把资源释放绑定到对象生命周期,减少手动 delete 带来的泄漏风险。
这背后其实就是 RAII 思想。
2. shared_ptr、unique_ptr、weak_ptr 的区别
这是必背。
unique_ptr:独占所有权,不能拷贝,可以移动,最轻量shared_ptr:共享所有权,靠引用计数管理weak_ptr:不增加引用计数,通常配合shared_ptr解决循环引用
3. 为什么 shared_ptr 会有循环引用问题
两个对象互相持有对方的 shared_ptr,引用计数都不为 0,谁也释放不了。
这时候一边通常要改成 weak_ptr。
4. 智能指针是不是就绝对安全
不是。
如果设计不当,照样可能:
- 循环引用
- 多线程引用计数开销
- 裸指针和智能指针混用导致所有权混乱
九、线程同步和 C++11,也越来越常问
1. 线程和进程的区别
简单说:
- 进程是资源分配基本单位
- 线程是 CPU 调度基本单位
- 同一进程内线程共享地址空间和大部分资源
2. 互斥锁的作用
多个线程访问共享资源时,保证同一时间只有一个线程进入临界区,避免数据竞争。
3. 死锁怎么产生
典型四个条件可以背,但更重要的是理解场景:
多个线程互相等待对方持有的资源,最终谁也走不下去。
4. C++11 带来了什么
高频关键词:
- 右值引用
- 移动语义
autonullptrlambdastd::thread- 智能指针标准化
unordered_map
如果面试官问“你最常用哪个”,别全背,挑两个讲清楚更自然。
十、最后说点实话
C++ 八股不是让你把每个概念讲成教材,而是要做到两件事:
第一,基础问题要答得稳。
像指针和引用、堆和栈、new 和 malloc、虚函数、智能指针,这些不能卡。
第二,机制问题要能往下接。
比如为什么要虚析构,为什么会迭代器失效,为什么会浅拷贝出问题,为什么 shared_ptr 会循环引用。
面试里最怕的不是“不会”,而是“只会第一句”。
你把每个高频题准备成“定义是什么 + 为什么存在 + 常见坑是什么”,基本就够用了。
高频问题清单
- C 和 C++ 的核心区别是什么?
- 指针和引用有什么区别?
const有哪些常见用法?static在不同位置分别是什么意思?- 堆和栈的区别是什么?
new/delete和malloc/free的区别是什么?- 什么是内存泄漏、野指针、悬空指针?
- 深拷贝和浅拷贝有什么区别?
- 拷贝构造和赋值运算符有什么区别?
- 左值、右值、右值引用分别是什么?
- 为什么要有移动语义?
- 什么是多态?
- 虚函数的实现原理大概是什么?
- 为什么基类析构函数通常要写成虚函数?
- 纯虚函数和抽象类是什么?
vector、list、deque的区别是什么?vector扩容会带来什么问题?map和unordered_map的区别是什么?- 为什么需要智能指针?
shared_ptr、unique_ptr、weak_ptr的区别是什么?shared_ptr为什么会循环引用?- 线程和进程的区别是什么?
- 互斥锁的作用是什么?
- 死锁是怎么产生的?
- C++11 你最常用的特性有哪些?
全部评论
(0) 回帖