C++开发必须要了解placement new的这些技巧
·
博主介绍:程序喵大人
- 35 - 资深C/C++/Rust/Android/iOS客户端开发
- 10年大厂工作经验
- 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
- 《C++20高级编程》《C++23高级编程》等多本书籍著译者
- 更多原创精品文章,首发gzh,见文末
- 👇👇记得订阅专栏,以防走丢👇👇
😉C++基础系列专栏
😃C语言基础系列专栏
🤣C++大佬养成攻略专栏
🤓C++训练营
👉🏻个人网站
开发了一个网站(希加加职业发展平台),可以对简历进行评估、并且能够根据你的简历内容进行面试押题预测,分享给大家。各位有需要的同学也可以去网站上实践体验一下,希望能帮助到你~
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致命)
面试技巧
别只说“在指定内存上构造对象”这句话。
加上这些词:对象池、内存复用、手动控制生命周期、构造不负责释放等。
码字不易,欢迎大家点赞,关注,评论,谢谢!
更多推荐



所有评论(0)