C++面试高频八股文汇总:别再只背概念了,真正卡人的就这几类

很多人背 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 默认是 publicclass 默认是 private

如果再往前一步,可以补一句:在 C++ 里两者本质能力差别不大,更多是编码风格和语义表达上的区别。

4. 空类占多少字节

通常是 1 字节。

原因不是它真有成员,而是为了保证每个对象在内存中有独立地址。

三、内存管理是绝对高频

1. 堆和栈的区别

这是经典题,但别只答“栈快堆慢”。

更完整一点:

  • 栈由编译器自动管理,存局部变量、函数参数等
  • 堆由程序员手动申请释放,或通过 RAII/智能指针间接管理
  • 栈空间通常较小,但分配释放快
  • 堆空间更灵活,但容易产生碎片、泄漏和悬空指针

2. new/deletemalloc/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. defineconst 的区别

  • define 是预处理替换,没有类型检查
  • const 是有类型的常量,作用域明确,更安全
  • 调试和编译期检查上,const 通常优于宏常量

五、拷贝控制、深浅拷贝、右值语义,常被一套连问

1. 深拷贝和浅拷贝

浅拷贝只是复制值本身,如果成员里有指针,就可能两个对象指向同一块资源。

深拷贝会复制资源本体,避免共享同一块动态内存。

为什么这题重要?

因为如果类自己管理堆资源,而你只用了默认拷贝构造和赋值,几乎就等着出双重释放。

2. 拷贝构造函数和赋值运算符区别

  • 拷贝构造:用一个已有对象初始化新对象
  • 赋值运算符:两个已存在对象之间赋值

这是两个完全不同的时机,很多人这里会混。

3. 为什么会有移动语义

因为有些对象管理的资源很重,拷贝代价高。

移动语义允许“资源所有权转移”,避免不必要的深拷贝,提高性能。

4. 左值和右值是什么

面试不要求你背标准定义,但要知道:

  • 左值通常有名字、可取地址、可持久存在
  • 右值通常是临时对象、字面量或即将销毁的值
  • T&& 能绑定右值,是移动语义和完美转发的重要基础

六、多态、虚函数、继承,这一块最容易被追问

1. 什么是虚函数

virtual 修饰的成员函数,允许子类重写,并通过基类指针或引用在运行时动态绑定。

2. 什么是多态

最常考的是运行时多态:

父类指针/引用指向子类对象,调用虚函数时表现出子类行为。

3. 虚函数表是怎么回事

不要求你讲到 ABI 细节,但起码知道:

编译器通常会为有虚函数的类维护一张虚函数表,对象里有个指向这张表的指针。调用虚函数时通过它做动态分派。

4. 为什么析构函数常常要写成虚函数

如果基类指针指向派生类对象,而基类析构不是虚函数,delete 基类指针时可能只调用基类析构,导致派生类资源没释放完整。

这题是高频陷阱题。只要涉及“多态基类”,析构通常就该是虚的。

5. 纯虚函数和抽象类

  • 纯虚函数写法:virtual void f() = 0;
  • 含有纯虚函数的类叫抽象类,不能实例化
  • 常用来定义接口规范

七、STL 和容器,不会真不太行

1. vectorlist 的区别

别背“数组 vs 链表”就结束。

核心对比:

  • vector 连续存储,随机访问快,尾插效率高
  • list 非连续存储,插删节点方便,但缓存命中差,随机访问不行
  • 实际工程里,vector 使用频率通常远高于 list

2. vector 扩容会发生什么

这是很爱考的一题。

要点:

  • 容量不够时会申请更大内存
  • 原有元素会被拷贝或移动到新空间
  • 旧空间释放
  • 原有迭代器、指针、引用可能失效

3. mapunordered_map 的区别

  • map 一般基于红黑树,元素有序,查找插入删除通常是 O(logn)
  • unordered_map 基于哈希表,平均 O(1),但最坏可能退化
  • unordered_map 不保证顺序,且依赖哈希函数和冲突处理

4. vectordeque 的区别

  • vector 连续存储,尾部操作友好
  • deque 支持头尾高效插入删除,但内存不完全连续
  • 如果频繁头插头删,deque 更合适

八、智能指针,基本已经成默认高频题了

1. 为什么要有智能指针

为了把资源释放绑定到对象生命周期,减少手动 delete 带来的泄漏风险。

这背后其实就是 RAII 思想。

2. shared_ptrunique_ptrweak_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 带来了什么

高频关键词:

  • 右值引用
  • 移动语义
  • auto
  • nullptr
  • lambda
  • std::thread
  • 智能指针标准化
  • unordered_map

如果面试官问“你最常用哪个”,别全背,挑两个讲清楚更自然。

十、最后说点实话

C++ 八股不是让你把每个概念讲成教材,而是要做到两件事:

第一,基础问题要答得稳。

像指针和引用、堆和栈、newmalloc、虚函数、智能指针,这些不能卡。

第二,机制问题要能往下接。

比如为什么要虚析构,为什么会迭代器失效,为什么会浅拷贝出问题,为什么 shared_ptr 会循环引用。

面试里最怕的不是“不会”,而是“只会第一句”。

你把每个高频题准备成“定义是什么 + 为什么存在 + 常见坑是什么”,基本就够用了。

高频问题清单

  1. C 和 C++ 的核心区别是什么?
  2. 指针和引用有什么区别?
  3. const 有哪些常见用法?
  4. static 在不同位置分别是什么意思?
  5. 堆和栈的区别是什么?
  6. new/deletemalloc/free 的区别是什么?
  7. 什么是内存泄漏、野指针、悬空指针?
  8. 深拷贝和浅拷贝有什么区别?
  9. 拷贝构造和赋值运算符有什么区别?
  10. 左值、右值、右值引用分别是什么?
  11. 为什么要有移动语义?
  12. 什么是多态?
  13. 虚函数的实现原理大概是什么?
  14. 为什么基类析构函数通常要写成虚函数?
  15. 纯虚函数和抽象类是什么?
  16. vectorlistdeque 的区别是什么?
  17. vector 扩容会带来什么问题?
  18. mapunordered_map 的区别是什么?
  19. 为什么需要智能指针?
  20. shared_ptrunique_ptrweak_ptr 的区别是什么?
  21. shared_ptr 为什么会循环引用?
  22. 线程和进程的区别是什么?
  23. 互斥锁的作用是什么?
  24. 死锁是怎么产生的?
  25. C++11 你最常用的特性有哪些?
全部评论

相关推荐

评论
1
2
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务