0

0

C++中的Placement new是什么?(如何在预分配的内存上构造对象)

裘德小鎮的故事

裘德小鎮的故事

发布时间:2026-02-12 17:10:51

|

262人浏览过

|

来源于php中文网

原创

placement new是new的重载形式,仅调用构造函数而不分配内存;普通new先分配内存再构造,而placement new直接在指定地址构造,需手动析构且不配对delete。

c++中的placement new是什么?(如何在预分配的内存上构造对象)

Placement new 是什么,和普通 new 有什么根本区别?

它不是“另一种 new”,而是 new 的一个重载形式,只负责调用构造函数,不做内存分配。普通 new 会先调用 operator new 分配内存,再在那块内存上调用构造函数;而 placement new 跳过分配步骤,直接在你指定的地址上调用构造函数。

  • 本质是语法糖:new (ptr) T(args...) 等价于手动调用 T::T(args...),但受 C++ 对象生命周期规则约束
  • 必须包含 <new></new> 头文件才能使用(否则编译报错:‘placement new’ declared here but never defined)
  • 不配对 delete —— 因为没分配,所以不能 delete,只能显式调用析构函数

怎么安全地在栈/静态/堆外内存上构造对象?

核心就三步:准备内存 → 构造 → 销毁。漏掉任何一步都可能引发未定义行为。

  • 内存必须满足对齐要求:比如 int 需 4 字节对齐,std::max_align_t 是最严对齐标准,推荐用 alignas(T) char buf[sizeof(T)] 声明缓冲区
  • 构造后不能用 delete,必须显式调用析构函数:obj.~T()
  • 若在动态分配的内存块(如 malloc 返回的)上调用 placement new,后续需用 free 释放原始内存,而非 delete
  • 示例(栈上构造):
    alignas(MyClass) char buf[sizeof(MyClass)];
    MyClass* p = new (buf) MyClass(42); // 构造
    p->~MyClass(); // 必须手动析构

为什么 operator delete 不会被调用?哪些场景下必须自己管内存?

placement new 不触发内存分配,因此编译器不会插入对 operator delete 的调用 —— 它压根不知道这块内存从哪来、该怎么还。

Knowt
Knowt

Knowt是一款AI驱动的在线学习工具

下载
  • 常见误操作:写了 new (ptr) T,却试图 delete p → 崩溃或静默 UB
  • 典型适用场景:
    • 内存池 / 对象池(预分配大块内存,反复构造/析构)
    • std::vectorstd::string 的内部实现(在已分配缓冲区中构造元素)
    • 嵌入式或实时系统中禁止动态分配,所有对象必须落在固定段内
  • 若你在 malloc 的内存上调用 placement new,记得:构造前检查 ptr != nullptr,析构后调用 free(ptr)

容易踩的坑:对齐、析构遗漏、类型别名陷阱

这是实际写错率最高的三个点,调试时往往表现为随机崩溃或值错乱。

立即学习C++免费学习笔记(深入)”;

  • char buf[N] 直接用于 placement new 构造 double 或自定义类?大概率未对齐 → 用 alignas(T) 显式声明缓冲区
  • 忘记手动调用析构函数:对象栈变量会自动析构,但 placement new 构造的对象不会,哪怕在函数末尾作用域结束
  • 使用 typedef 或 using 别名时,sizeofalignas 必须基于最终类型,不是别名本身:using T = std::vector<int></int>,则要用 alignas(T),不是 alignas(std::vector<int>)</int>(虽然等价,但可读性差,易出错)
  • 不支持数组语法:new (ptr) T[10] 是非法的;要构造数组得循环调用,或用 std::uninitialized_construct_n(C++17 起)

C++ 标准不保证 placement new 构造的对象能被常规指针操作安全访问,一切前提是你提供的内存合法、对齐、未越界、且生命周期管理完全自主 —— 这部分没有编译器兜底。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

typedef和define区别
typedef和define区别

typedef和define区别在类型检查、作用范围、可读性、错误处理和内存占用等。本专题为大家提供typedef和define相关的文章、下载、课程内容,供大家免费下载体验。

113

2023.09.26

c语言typedef的用法
c语言typedef的用法

c语言typedef的用法有定义基本类型别名、定义结构体别名、定义指针类型别名、定义枚举类型别名、定义数组类型别名等。本专题为大家提供typedef相关的文章、下载、课程内容,供大家免费下载体验。

101

2023.09.26

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

708

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

560

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

206

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

4

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9.3万人学习

C 教程
C 教程

共75课时 | 4.7万人学习

C++教程
C++教程

共115课时 | 17.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号