C++面试题更新 2026-08-05

在 C++ 中,为什么使用 new[] 分配的对象数组必须与 delete[] 配对释放?请说明原因,并解释配对不当可能导致的后果。

编码实现风险判断技术原理C++

考察说明

考查对 C++ 动态数组内存管理底层机制的理解,包括 operator new[] 与 operator delete[] 的配对语义。

回答思路

  1. 【回答框架 1】new[] 分配对象数组时,会先调用 operator new[] 申请内存,然后依次调用每个元素的构造函数;delete[] 释放时,先逆序调用每个元素的析构函数,再调用 operator delete[] 归还内存。编译器通常会在分配的数组头部存储元素个数,以便 delete[] 知道调用多少次析构函数。
  2. 【回答框架 2】如果使用 delete 而不是 delete[] 释放 new[] 分配的内存,行为是未定义的。对于内置类型或平凡析构函数的类,可能看起来正常,因为不涉及析构调用,但标准上仍属未定义行为;对于有非平凡析构函数的类,会导致析构函数未被调用,造成资源泄漏,且可能因跳过头信息或错误释放预期而导致堆损坏。
  3. 【回答框架 3】如果使用 delete[] 释放 new 单个对象,同样是未定义的,可能过度解析头信息,导致越界访问或错误释放。因此,配对规则的核心是让编译器的释放逻辑与分配时的内部布局保持一致。
  4. 【回答框架 4】配对意味着 new[] 对应 delete[],new 对应 delete,malloc 对应 free,不能混用。实际编程中应优先使用 std::vector 等容器来避免手动管理,降低误用风险。
  5. 【回答框架 5】在现代 C++ 中,建议使用智能指针(如 std::unique_ptr<T[]>)管理数组,或直接用容器,以提供自动正确释放,同时避免显式配对带来的负担。
  6. 【关键点 1】new[] 分配时记录元素数目,delete[] 根据记录调用析构函数。
  7. 【关键点 2】delete 代替 delete[] 会跳过析构,可能资源泄漏;未定义行为。
  8. 【关键点 3】delete[] 释放 new 单个对象会错误解析头信息,也可能未定义。
  9. 【关键点 4】配对规则是为了保持内存布局和析构次数一致,避免堆损坏。
  10. 【关键点 5】优先使用 std::vector 或智能指针数组,避免手动配对。
  11. 【易错点 1】不要以为内置类型数组用 delete 也安全,标准上仍是未定义行为。
  12. 【易错点 2】不要假设所有编译器的实现细节(如头部是否存储计数),依赖实现是不可移植的。
  13. 【易错点 3】混用 new[] 与 delete 可能导致堆损坏,调试困难。