本次全部对话完整知识点汇总
对话完整脉络:先拿到C++核心面试清单 → 深度深挖6大块重难点 → 进阶大厂专题(noexcept、4种强制转换、多线程‑内存序、forward、SFINAE),下面把从头到尾全部内容整理成一份完整复盘笔记
第一阶段:初始 C++ 核心题库(第一轮基础知识点)
面向对象、多态
- 多态:静态多态(编译期:函数重载、模板)、动态多态(运行期:虚函数 + 继承 + 基类指针/引用)
- 底层原理:虚函数表 vtable、对象头部虚指针 vptr、晚绑定
- 基类虚析构:delete基类指针释放派生对象时,避免派生类资源泄漏
- 对象切片:派生对象赋值给栈上基类对象,派生独有成员被切掉;解决:用指针/引用接收
override:校验虚函数重写签名;final:禁止类继承 / 禁止虚函数重写
RAII、内存管理
- RAII(资源获取即初始化):资源生命周期绑定局部对象生命周期;构造申请资源,析构自动释放;异常安全,防泄漏。
new/deletevsmalloc/free- malloc/free:C库函数,只处理原始内存,不调用构造/析构
- new/delete:C++运算符,分配内存+调用构造;释放前调用析构;new失败抛bad_alloc
- 禁止混用
new[] / delete[]配对原则,数组隐藏计数,混用delete造成未定义行为
智能指针
unique_ptr:独占所有权、禁止拷贝,仅移动;无引用计数shared_ptr:共享所有权;引用计数use_count;多线程计数器原子、对象操作非线程安全weak_ptr:弱引用,不增加强计数,解决shared_ptr循环引用
右值引用、移动语义
- 左值、右值区分;
std::move仅类型转换,不移动数据 - 移动构造:转移堆资源所有权,减少深拷贝开销
const / static
- const各种修饰场景:常量变量、常量指针、指针常量、const成员函数
- static:局部静态变量、类静态成员变量、静态成员函数(无this指针)
STL容器
- vector底层连续数组、扩容机制(1.5‑2倍)、迭代器失效
- map(红黑树有序 O(logn)) vs unordered_map(哈希表无序,平均O(1))
- vector / list迭代器失效区别
继承
- 三种继承:public / protected / private继承访问权限变化
- 菱形继承问题,虚继承virtual解决方案
C++11 Lambda
捕获方式[]、[=]、[&]、mutable关键字
第二阶段:深度深挖专题1(你指定深入讲解)
1.new[] / delete[]深度
- new[]会在返回指针前面隐藏存储数组元素个数N
- delete[]逆序调用析构
- new[] + delete(不带[]):只析构第一个对象,内存泄漏+未定义行为
- 内置类型int无析构混用侥幸不出错,依然UB
2.shared_ptr循环引用 + weak_ptr完整解析
- shared_ptr结构:对象指针 + 控制块(use_count、weak_count)
- 循环引用成因:两个对象互相保存shared_ptr,use_count永远不能归零,内存泄漏
- weak_ptr:弱引用,只修改weak_count,不增加use_count;lock()升级shared_ptr;expired()判断对象是否销毁
- 解决方案:双向依赖一边shared_ptr拥有所有权,另一边weak_ptr观察者
3.std::move、移动构造、移动赋值
- std::move源码本质:static_cast转换成右值引用,无任何资源搬运
- 左值、纯右值、将亡值
- 移动构造接管堆资源,源对象置空,防止二次释放
- noexcept至关重要:vector扩容时,如果移动构造没有noexcept,容器放弃移动,降级拷贝构造
- 被move后的对象处于有效但未指定状态
4.菱形继承(钻石继承)详解
- 普通菱形继承:产生两份父类副本、二义性、内存冗余
- virtual虚继承:生成唯一一份公共父类
- 底层内存布局:vbptr虚基指针,虚基表存放偏移量;虚基类放在内存末尾
- 构造规则:最远派生类负责虚基类的构造函数
5.大厂进阶面试题第一波
虚函数表和虚基表区别;构造函数不能为虚函数原因;空类大小1字节;volatile不能保证线程安全;RVO/NRVO返回值优化;右值引用延长临时生命周期;完美转发std::forward;迭代器失效;SFINAE概念
第三阶段:深度深挖专题2 noexcept + 4种强制转换
1. noexcept
- C++11异常说明符,函数承诺不会抛出异常;条件式noexcept(表达式)
- 契约而非强制;noexcept函数抛异常 → terminate()直接终止程序
- 核心作用:影响STL vector扩容是否选用移动构造
- noexcept运算符编译期检测表达式是否可能抛异常
- 虚函数重写时noexcept必须兼容
2. 四种强制转换
static_cast:编译期检查,良性转换,数值转换,向上继承转换;向下转型不安全,无运行校验dynamic_cast:运行时检查、依赖RTTI、类必须含有虚函数;指针失败返回nullptr,引用失败抛异常;支持横向(兄弟类)转换const_cast:唯一修改const/volatile限定符;不能修改原生const对象(UB)reinterpret_cast:二进制比特原样重解释;指针整数互转,底层开发使用,可移植性差- C风格强制转换缺点:依次尝试多种转换,意图模糊,现代C++不推荐
第四阶段:深度深挖专题3 多线程原子、内存序、forward、SFINAE
1.寄存器、volatile、std::mutex、std::atomic
- 寄存器:CPU高速缓存;编译器优化将变量缓存寄存器,线程看不见内存上新值
- volatile:禁止编译器优化缓存;不能保证原子性,不能阻止CPU指令重排,不可用于线程同步
- std::mutex互斥锁:阻塞悲观锁;保证原子性、可见性、有序性;线程休眠‑内核切换开销大;保护一段临界区代码
- std::atomic原子变量:硬件原子指令实现无锁并发;保证单变量原子性;性能高于锁
2.C++11 memory_order 六大内存序(控制编译器+CPU指令重排)
- memory_order_relaxed:宽松序;仅原子性;无顺序屏障,适合计数器
- memory_order_release:store写屏障,前面指令不能重排到写之后
- memory_order_acquire:load读屏障,后面指令不能重排到读之前;acquire‑release配对建立happen‑before同步关系
- memory_order_acq_rel:读写双向屏障,用于fetch_add等读‑改‑写原子操作
- memory_order_consume:弱化acquire,现已废弃
- memory_order_seq_cst:顺序一致性,atomic默认内存序;最强全局屏障,开销最高
3.std::forward完美转发 & 万能引用、引用折叠
- 万能引用:模板
T&&≠右值引用;支持绑定左值/右值;引用折叠规则 - 具名变量永远为左值;右值传入模板函数内部后丢失右值属性
- std::forward(arg):保留参数原始左/右值属性,原样转发
- move vs forward对比:move无条件转为右值;forward按需转换,用于模板转发场景
4.SFINAE
全称 Substitution Failure Is Not An Error(替换失败不是错误)
- 生效时机:模板参数替换阶段;非法代码不会报编译错误,直接舍弃当前重载
- 函数体内部报错不属于SFINAE
- 用途:C++17前类型萃取检测类成员;C++20优先concept替代SFINAE
全对话高频易混考点对照表(面试必背)
- shared_ptr循环引用 → weak_ptr解决
- 菱形继承二义性 → virtual虚继承
- new[] ↔ delete[]严格配对
- std::move:仅转换;std::forward:完美转发
- volatile ≠ 线程安全;atomic提供原子性;mutex阻塞锁保护大片逻辑
- 移动构造不加noexcept → vector扩容放弃移动,降级拷贝
- static_cast向下转型快不安全;dynamic_cast向下转型安全带RTTI开销
如果你需要,我可以把这份完整内容导出成可打印精简背诵版。


0 条回复
还没有留言,来说点什么吧。