Placement New 是 operator new 的重载形式,跳过内存分配仅执行构造;普通 new 则先分配内存再构造。必须用于对象池、嵌入式系统、自定义容器、序列化等需精细控制内存与生命周期的场景。

Placement New 是什么?它和普通 new 有什么本质区别?
Placement New 不是独立的“新运算符”,而是 operator new 的一个重载形式,它跳过内存分配阶段,只执行对象构造。普通 new 做两件事:调用 operator new 分配内存 → 在该地址上调用构造函数;而 Placement New 只做后半部分——你必须自己提供一块**已分配、足够大、满足对齐要求**的原始内存。
哪些场景必须用 Placement New?
常见于需要精细控制对象生命周期或内存布局的底层场景:
- 对象池(Object Pool):预分配一大块内存,反复在其中构造/析构对象,避免频繁堆分配
- 嵌入式或实时系统:禁止运行时动态分配,所有内存必须静态或栈上提前预留
- 自定义容器(如
std::vector内部):在已申请的 raw buffer 中逐个构造元素 - 序列化反序列化:将二进制数据直接“复活”为对象(需确保位布局兼容且无虚函数等复杂结构)
怎么正确使用 Placement New?漏掉哪一步都会出问题
必须严格遵循“构造 → 使用 → 显式析构 → (可选)复用内存”四步。尤其注意:不能用 delete 销毁 Placement New 构造的对象——因为没用对应 operator new 分配。
char buffer[sizeof(MyClass)]; // 预留足够空间 MyClass* obj = new (buffer) MyClass(42); // Placement New:仅构造obj->do_something();
立即学习“C++免费学习笔记(深入)”;
obj->~MyClass(); // 必须显式调用析构函数!否则资源泄漏
// 此时 buffer 可再次用于 new (buffer) MyClass(...) 或其他类型
容易踩的坑:对齐、大小、析构缺一不可
最常被忽略的是内存对齐和 size 检查:
-
buffer地址必须满足alignof(MyClass)对齐要求,否则行为未定义(x86-64 上常见 8/16 字节对齐) -
sizeof(buffer)必须 ≥sizeof(MyClass),且若类含虚函数或继承,还需考虑 vptr/vtable 布局 - 忘记调用
obj->~MyClass():成员变量的析构函数不会自动运行,RAII 资源(如文件句柄、锁)无法释放 - 误用
delete obj:触发未定义行为,因obj并非由全局operator new返回
真正难的不是语法,是保证整块内存的生命周期管理与对象生命周期完全同步——稍有错位,就是悬垂指针或双重析构。









