博主介绍:程序喵大人

开发了一个网站(希加加职业发展平台),可以对简历进行评估、并且能够根据你的简历内容进行面试押题预测,分享给大家。各位有需要的同学也可以去网站上实践体验一下,希望能帮助到你~

placement new 是 C++ 中的一种特殊机制,它会在预先分配好的内存地址上构造对象,不涉及任何内存分配操作。而且它完全绕过了默认的堆内存分配过程,是底层内存管理的关键机制。

什么是placement new

说白了,它就是让你自己准备内存,然后指定位置构造对象。

不像普通 new那样内存也帮你申请,placement new 只干一件事:构造!

为什么要有placement new

很多底层系统,比如内存池、共享内存、嵌入式开发,

都不希望频繁申请释放内存,所以就先分配好一大块,自己手动控制用法。

这个时候,placement new 就超好用!

核心特性

#include <new>  // 必需的头文件

void* memory = std::malloc(sizeof(MyClass));  // 1. 预先分配内存
MyClass* obj = new (memory) MyClass(params);  // 2. 在此内存构造对象

工作原理

不分配内存:编译器将 new (addr) T(...) 转换为:

void* __addr = addr;             // 接受用户指定的地址
T* __ptr = static_cast<T*>(__addr);
__ptr->T::T(params);             // 直接在此地址调用构造函数
return __ptr;

对应的 operator new:底层调用专门的重载版本:

void* operator new(std::size_t, void* p) noexcept {
    return p;  // 直接返回输入地址
}

关键用途

自定义内存管理

// 内存池示例
void* pool = allocate_memory(sizeof(MyClass)); 
MyClass* obj = new (pool) MyClass(); // 直接构造

栈上对象构造

alignas(MyClass) char buffer[sizeof(MyClass)]; // 栈内存
new (buffer) MyClass();  // 在栈上构造

共享内存

void* shared_mem = map_shared_memory("/region1");
new (shared_mem) SharedData();  // 在共享内存构造对象

容器实现

// std::vector 的内部实现示例
void* new_storage = allocate(new_capacity);
for (auto& elem : old_items) {
    new (new_storage++) T(std::move(elem)); // 移动构造到新内存
}

生命周期管理

手动析构,必须手动调用析构函数

obj->~MyClass();  // 必须显式调用析构函数

内存释放,不能delete。

std::free(memory);  // 释放原始内存(不能 delete obj!)

底层视角

; x86_64 示例 (GCC)
lea     rdi, [rbp-32]   ; 获取内存地址 (代替 malloc)
call    MyClass::MyClass(int) ; 直接调用构造函数
mov     QWORD PTR [rbp-8], rax ; 返回对象指针

典型误用

// 错误1:直接 delete placement new 的对象
MyClass* obj = new (mem) MyClass;
delete obj;  // 未定义行为! 应调用析构 + 释放原始内存

// 错误2:忽略对齐要求
char buffer[sizeof(MyClass)]; 
new (buffer) MyClass();  // 可能因对齐错误崩溃 (x86宽容, ARM致命)

面试技巧

别只说“在指定内存上构造对象”这句话。

加上这些词:对象池、内存复用、手动控制生命周期、构造不负责释放等。

码字不易,欢迎大家点赞,关注,评论,谢谢!

更多推荐