2. C++语言核心高频问题:虚函数与多态、智能指针、内存管理、RAII
面试官在本主题中重点考察对C++三大核心机制(运行时多态、资源管理、异常安全)的理解深度。要求不仅知道“怎么用”,还要能解释“为什么这样设计”以及“对比其他方案的优缺点”。以下是高频问题的回答框架与实战要点。
📊 核心知识点速查表
| 主题 | 关键概念 | 常见考查点 | 避坑提醒 |
|---|---|---|---|
| 虚函数与多态 | vptr/vtable、动态绑定、重写(override) | 虚函数能否内联?构造/析构中调用虚函数的行为 | 不要忘记virtual析构函数 |
| 智能指针 | shared_ptr/weak_ptr/unique_ptr、引用计数、循环引用 | 控制块大小、线程安全、与裸指针混用风险 | 避免shared_ptr循环引用导致内存泄漏 |
| RAII | 资源获取即初始化、栈对象管理、异常安全 | 与智能指针关系、自定义RAII封装、ScopeGuard | 析构函数不可抛出异常 |
| 内存管理 | new/delete与malloc/free、对象池、内存对齐 | placement new、operator new重载、内存碎片 | new[]必须对应delete[] |
❓ 面试问题:请解释C++虚函数的实现原理,以及多态在运行时的行为。
🎯 面试官考察点:
- 是否理解虚表(vtable)和虚指针(vptr)的内存布局
- 能否说清动态绑定的触发条件
- 是否知道虚函数在构造函数/析构函数中的特殊行为
📝 回答框架: 定义虚函数 → vptr与vtable关系 → 动态绑定过程 → 纯虚函数与抽象类 → 性能与限制
💬 简短示例回答: 每个含有虚函数的类有一个虚函数表,对象头中存储vptr指向该表。调用虚函数时通过vptr找到实际函数地址。存在继承且函数签名相同时,派生类覆盖基类虚函数。注意构造/析构期间对象类型是当前构造的类,不会发生动态绑定。
🔍 可能追问: 虚函数能否被声明为内联?多继承下的vptr布局?C++11的final和override作用?
⚠️ 避坑提醒: 不要在构造函数或析构函数中调用虚函数,因为此时派生类部分尚未构造/已被析构,动态绑定无效。
❓ 面试问题:请比较std::unique_ptr、std::shared_ptr和std::weak_ptr的区别及使用场景。
🎯 面试官考察点:
- 是否掌握三种指针的所有权语义
- 能否说明引用计数的工作原理及线程安全问题
- 是否知道如何避免循环引用
📝 回答框架: 独占所有权 vs 共享所有权 → shared_ptr引用计数 & 控制块 → weak_ptr解决循环引用 → 性能差异与使用建议
💬 简短示例回答: unique_ptr独占资源,轻量但禁止拷贝;shared_ptr通过控制块管理引用计数,支持拷贝但开销较大;weak_ptr配合shared_ptr使用,不增加引用计数,常用于观察者模式或打破循环。优先使用unique_ptr,需要共享时再考虑shared_ptr。
🔍 可能追问: make_shared与直接new构造shared_ptr的区别?控制块内存位置?自定义删除器的实现?
⚠️ 避坑提醒: 不要将同一个裸指针分别构造两个shared_ptr,会导致两次析构;使用weak_ptr.lock()前务必检查是否过期。
❓ 面试问题:RAII的核心思想是什么?如何利用RAII实现资源管理及异常安全?
🎯 面试官考察点:
- 是否理解RAII与异常安全的关系
- 能否举例说明自定义RAII封装(如锁、文件句柄)
- 是否了解C++11的移动语义对RAII的优化
📝 回答框架: 资源获取即初始化 → 析构函数自动释放 → 异常安全基本保证 → 智能指针是RAII典范 → 移动语义避免资源复制
💬 简短示例回答: RAII将资源生命周期绑定到栈对象:构造函数获取资源,析构函数安全释放。例如std::lock_guard自动管理mutex,即使函数中途抛出异常,锁也会被释放。这是C++异常安全的基础,也避免了手动new/delete配对。
🔍 可能追问: 什么是“强异常安全保证”?copy-and-swap技术如何实现?RAII与垃圾回收的对比?
⚠️ 避坑提醒: RAII对象的析构函数必须不能抛出异常;如果需要多个资源,建议按依赖顺序封装为嵌套RAII对象,避免资源泄漏。
💡 面试加分技巧: 在回答虚函数问题时,主动画出内存布局图(vptr、vtable、对象内容)会极大提升面试官印象;提到C++11/14/17特性(如override、final、std::make_shared)展示持续学习能力。
📌 记忆口诀: 虚函数靠表,多态靠指针;智能指针三种权,RAII保安全;内存管理先配对,构造析构不乱配。
⚠️ 高阶提醒: 面试高频陷阱——问“智能指针循环引用如何排查?”回答:使用weak_ptr打断闭环,或使用工具如Valgrind/AddressSanitizer检测引用计数泄漏。