第3章 内存管理与智能指针
内存管理是C++面试的“必考科目”,贯穿栈/堆分配、对象生命周期、智能指针三大核心。面试官通过该主题考察你对资源控制的理解深度、对RAII的运用能力,以及排查内存泄漏的实战经验。本章围绕三个高频问题展开,助你建立系统的回答框架。
知识结构:栈 vs 堆 核心对比
| 维度 | 栈 (Stack) | 堆 (Heap) |
|---|---|---|
| 分配方式 | 自动分配/释放 | 手动 new/delete 或智能指针 |
| 生命周期 | 随函数调用自动销毁 | 显式释放或智能指针引用计数归零 |
| 性能 | 纳秒级,连续内存 | 微秒级,需查找空闲块 |
| 大小限制 | 通常 1~8 MB | 受虚拟内存限制(如 4G) |
| 典型问题 | 栈溢出(递归过深) | 内存泄漏、野指针 |
🎯 问答卡片 1:栈与堆的区别
面试问题:请解释 C++ 中栈(stack)和堆(heap)的区别。
面试官考察点:是否理解两种内存区域的根本差异(分配方式、生命周期、性能);能否延伸到RAII和资源管理。
回答框架:① 对比分配方式(自动 vs 手动)→ ② 生命周期(函数作用域 vs 显式释放)→ ③ 性能与容量区别 → ④ 风险:栈溢出 vs 内存泄漏。
简短示例回答:栈由编译器自动管理,每调用函数分配连续空间,速度快但容量小;堆需程序员通过 new/delete 或智能指针分配,生命周期可跨函数,但易产生碎片和泄漏。现代C++推荐用智能指针将堆管理栈化,即RAII。
可能追问:全局变量和静态变量在哪个区?栈帧结构是怎样的?如何用代码验证栈大小?
🎯 问答卡片 2:智能指针三剑客
面试问题:说说 unique_ptr、shared_ptr 和 weak_ptr 的区别及应用场景。
面试官考察点:是否掌握三种指针的所有权模型、控制块结构、循环引用问题的解决方案。
回答框架:① unique_ptr:独占所有权,轻量无引用计数 → ② shared_ptr:共享所有权,引用计数线程安全 → ③ weak_ptr:观察指针,不增加计数,解决循环引用 → ④ 性能开销与使用原则。
简短示例回答:unique_ptr 用于独占资源,如工厂返回的对象;shared_ptr 用于多个协作者共享资源,控制块管理引用计数;weak_ptr 作为观察者,打破 shared_ptr 循环引用,常用于缓存或观察者模式。优先使用 unique_ptr,必要时再上 shared_ptr。
可能追问:如何自定义删除器?shared_ptr 线程安全吗?控制块在哪里分配?make_shared 的优势?
🎯 问答卡片 3:内存泄漏检测与预防
面试问题:你如何检测和避免 C++ 中的内存泄漏?
面试官考察点:是否具备排查泄漏的工程能力;是否了解静态分析、运行时工具;能否从设计层面避免泄漏。
回答框架:① 设计预防:RAII + 智能指针(避免裸 new)→ ② 静态检测:cppcheck、Clang-Tidy → ③ 运行时工具:Valgrind、AddressSanitizer → ④ 代码审查与压力测试。
简短示例回答:首先在编写时坚持RAII,非托管资源用 unique_ptr 封装;其次在CI中集成 AddressSanitizer,快速捕捉越界和泄漏;若遇到复杂项目,再用 Valgrind 做全量追踪。线上环境通常重试机制 + 资源上限兜底。
可能追问:new 和 malloc 混用的风险?如何在长期运行服务中定位累积泄漏?C++17 std::pmr 对内存管理的影响?