60 秒回答模板

C++ 的 new 表达式不是简单的 malloc。它通常分两步:先调用 operator new 申请足够且满足对齐要求的原始内存,再在这块内存上调用构造函数建立对象,最后返回类型化指针。如果构造函数抛异常,运行时会自动调用对应 operator delete 释放刚申请的内存。delete 的顺序相反:先调用析构函数释放对象资源,再调用 operator delete 归还原始内存。new/delete 要成对使用,new[]/delete[] 也要成对使用;placement new 只在已有内存上构造对象,不负责分配,析构和释放要由调用方管理。

考点 核心机制与工程取舍
难度 中高频面试题
回答目标 按定义、机制、场景讲清楚

深入解析

01

new 表达式两阶段

第一阶段是内存分配,调用 operator new 得到一块原始字节区域;第二阶段是对象构造,在这块内存上运行构造函数,让对象不变量成立。返回值是具体类型指针,而不是未初始化 void 指针。

02

operator new 可定制

operator new 是可重载的分配函数,类可以定义自己的版本,也可以使用全局版本。它只负责分配内存和对齐,不负责调用构造函数;这点要和 new 表达式区分。

03

构造失败要回滚

如果内存分配成功但构造函数抛异常,C++ 会调用匹配的 operator delete 释放原始内存,避免泄漏。已经构造完成的子对象也会按规则析构,这体现了异常安全。

04

delete 顺序相反

delete 先执行析构函数,让对象释放文件句柄、锁、堆内存等资源,再调用 operator delete 释放对象占用的原始内存。malloc/free 只管字节分配,不会构造或析构对象。

05

数组和 placement new 边界

new[] 会构造多个元素,并需要 delete[] 逐个析构;和 delete 混用是未定义行为。placement new 在指定地址构造对象,常用于内存池和容器实现,调用方必须显式析构,并按内存来源释放。

易错点

  • 把 new 等同于 malloc,漏掉构造函数、类型化返回和异常语义。
  • 混用 new/delete、new[]/delete[]、malloc/free,造成未定义行为。
  • 不知道构造函数抛异常时会调用 operator delete 回收内存。
  • 把 placement new 当成会分配内存的普通 new。

面试官追问

new 和 malloc 有什么区别?

new 表达式会分配内存、调用构造函数并返回类型化指针,失败通常抛 bad_alloc;malloc 只分配字节并返回 void*,不会初始化对象,失败返回 null。

operator new 和 new operator 是一回事吗?

不是。new 表达式是语言层面的对象创建过程;operator new 是其中用于分配原始内存的函数,可以被重载。面试中常把它们混叫,但原理上要分清。

placement new 用来做什么?

它在调用方提供的地址上构造对象,不分配内存。常用于内存池、容器预分配空间、共享内存等场景。之后通常要手动调用析构函数。

为什么 new[] 必须配 delete[]?

数组 new 需要记录或知道元素个数,以便 delete[] 逐个调用析构函数。用 delete 释放 new[] 得到的指针是未定义行为,析构和释放都可能不正确。