当前位置: 首页 > article >正文

operator new 和 placement new

C 动态内存管理深度解析从operator new到 placement new一、概念正本清源new 表达式 vsoperator new函数很多初学者把 new 当作一个不可分割的整体但实际上 C 把动态内存的两个职责拆得很开步骤new 表达式 (new T(...))delete 表达式 (delete p)1调用operator new申请内存调用析构函数销毁对象2在内存上调用构造函数调用operator delete释放内存重要事实和operator这类运算符不同operator new/operator delete不能重载 new/delete 表达式本身——你只能改变其中分配/释放内存那一步不能改变 new 表达式先分配再构造、delete 表达式先析构再释放这一固定语义。Widget* p new Widget(42);// 等价于void* mem operator new(sizeof(Widget));Widget* p new (mem) Widget(42); // placement new 只构造二、operator new/operator delete定制规则2.1 作用域要求必须定义在 全局作用域 或 类作用域。当作为类成员定义时它们是 隐式静态的implicit static。原因很自然operator new在对象构造之前调用 → 此时对象尚不存在没有this。operator delete在对象销毁之后调用 → 此时对象已不存在没有this。2.2 签名要求// operator newvoid* operator new(size_t size); // 单对象void* operator new[](size_t size); // 数组// 第一个参数必须是 size_t且不能有默认实参// 返回类型必须是 void*// operator deletevoid operator delete(void* p) noexcept; // 单对象void operator delete[](void* p) noexcept; // 数组// 第一个参数必须是 void*// 返回类型必须是 void类成员版本的operator delete还可以多接收一个size_t参数初值为指针所指对象的字节数——这在销毁继承体系中带虚析构函数的对象时特别有用实际字节数取决于动态类型。2.3 一个简单的实现基于malloc/freeC 从 C 继承了malloc/free位于cstdlib它们是搭建自定义operator new的基石void* operator new(size_t size) {if (void* mem std::malloc(size))return mem;throw std::bad_alloc();}void operator delete(void* mem) noexcept {std::free(mem);}三、唯一不可重载的特殊形式void* operator new(size_t, void*); // 标准库保留禁止用户重载这就是 placement new 函数。它的标准实现极其简单void* operator new(size_t, void* p) noexcept { return p; }它不分配任何内存只是把传入的指针p原封不动返还让 new 表达式的下一步——构造函数——在p指向的内存上就地构造。四、零长数组合法但特殊的new T[0]char arr[0]; // 错误不能定义 0 长度数组char* cp new char[0]; // 合法但 *cp 不能解引用new T[0]返回的指针有几个明确保证非空 且 唯一不与任何其他new返回的指针相等。行为类似 过尾指针 / off-the-end iterator可以参与比较for (p; p ! end; p)自然终止。可以加 0、减 0自身相减得 0。不能解引用——它不指向任何元素。这一设计让 用一对指针描述一个空区间 的写法天然成立无需特判n 0。五、Placement New 详解5.1 它是什么Placement new 是operator new的一个标准全局重载版本其原型为void* operator new(size_t, void* p) noexcept { return p; }它允许我们在一段已经分配好的内存无论在堆还是在栈上构造新对象。5.2 为什么需要它普通new需要在堆上查找足够大的空闲块这有两个代价耗时不确定堆查找速度慢且不可预测。可能失败内存不足会抛std::bad_alloc。Placement new 把分配和构造彻底解耦内存可预先分配并反复复用避免碎片。构造时间是 常数不会中途内存不足。非常适合实时性要求高、运行不希望被打断的场景嵌入式、L1/L2 实时调度、内存池等。5.3 标准五步用法class Foo {char cc;float f;public:void print() { std::cout ADDR: this \n; }void set_f(float v){ f v; }void get_f() const { std::cout f f \n; }};// 1) 分配内存堆或栈均可char* buff new char[sizeof(Foo) * N];std::memset(buff, 0, sizeof(Foo) * N);// 2) 在已分配内存上构造对象这一步才是 placement newFoo* pfoo new (buff) Foo;// 3) 使用对象pfoo-print();pfoo-set_f(1.0f);pfoo-get_f();// 4) 显式调用析构函数关键placement new 没分配内存// 所以不能用 delete pfoo——那会去释放 buff 之外的东西pfoo-~Foo();// 5) 释放最初分配的内存与第 1 步对应delete[] buff; // 若 buff 在栈上则跳出作用域自动释放5.4 数组形式的隐含开销C 标准对placement operator new[]有特别说明placement operator new[] needs implementation-defined amount of additional storage to save a size of array.也就是说placement new 数组版需要额外的几个字节实现定义通常为sizeof(size_t)来记录数组元素个数。如果你打算用 placement new 创建 N 个对象的数组必须为这个隐藏的长度头也预留空间char* buf new char[N * sizeof(MyClass) sizeof(int)];MyClass* arr new (buf) MyClass[N];六、案例剖析auto var *new Widget(42); delete var;源代码关键路径已略去打印细节class Widget {int value{};public:Widget(int v 10) : value{v} { std::cout Widget(int) constructor\n; }~Widget() {if (value 0) std::cout 0~destructor: this \n;else { value 0; std::cout ~destructor: this \n; }}void print() { std::cout value: value : this \n; }// ... 拷贝/移动构造、赋值省略};int main() {auto var *new Widget(42);var.print();delete var;}6.1 逐句拆解表达式行为输出new Widget(42)①operator new分配sizeof(Widget)字节② 在该内存上调用Widget(int)Widget(int) constructor*new Widget(42)解引用new返回的指针得到 左值Widget—auto var *...引用绑定到那块堆内存上的对象没有发生任何拷贝—var.print()普通成员调用value:42 : 0xADDRvar取引用绑定对象的地址就是new返回的原指针—delete var① 调用~Widget()②operator delete释放该指针指向的内存~destructor:0xADDR6.2 是否泄漏——关键洞察很多人误以为 用引用接住*new一定会泄漏因为指针丢了。这是 不对的var会精确地恢复出new返回的地址——只要var是直接绑定到*new T(...)这种刚出炉的对象var与原始指针二进制完全相同。因此delete var等同于delete p析构和释放都会被正确触发。真正的风险不在于泄漏而在于可读性与可维护性类型不再表达所有权——读者很难一眼看出var背后是堆对象。异常安全极差——若var.print()抛异常delete var永远执行不到立刻泄漏。多重继承下var的地址可能与new返回的指针不同涉及指针调整此时delete var会触发未定义行为。结论上述写法在语法上合法、在简单场景下不泄漏但属于反模式。生产代码应当使用std::unique_ptrWidget或值语义栈上对象。6.3 预期完整输出Widget(int) constructorvalue:42 : 0xADDR~destructor:0xADDR七、易错点速查表误区真相重载 new 表达式不可能只能重载operator new这一步void* operator new(size_t, void*)自定义非法标准库保留new T[0]报错合法返回唯一非空但不可解引用的指针placement new 后用delete错误必须显式调用析构再用对应方式释放原始内存auto v *new T; delete v;一定泄漏简单场景下不会但在多重继承、异常路径下极易出问题malloc出来的内存可以delete未定义行为必须malloc/free、new/delete严格成对八、给工程实践的建议优先使用 RAIIstd::unique_ptr/std::shared_ptr/ 容器 / 栈对象 ——几乎可以消除手写new/delete的需求。真要自定义内存管理时成对实现operator new与operator delete并保持类成员版本与基类签名匹配避免切片释放失败。内存池场景用 placement new 在预分配的 buffer 上反复构造/析构构造时间常数化杜绝运行期内存不足。严守对称原则new↔deletenew[]↔delete[]placement new↔ 显式析构 原 buffer 的对应释放方式malloc↔free掌握了new 表达式 operator new 构造函数这个分解几乎所有 C 动态内存的奇怪行为都会变得自然——包括 placement new、零长数组、自定义分配器、内存池乃至std::vector内部如何把容量与大小解耦。这是从会用 new 走向理解内存模型的关键一步。

相关文章:

operator new 和 placement new

C 动态内存管理深度解析:从 operator new 到 placement new一、概念正本清源:new 表达式 vs operator new 函数很多初学者把 "new" 当作一个不可分割的整体,但实际上 C 把动态内存的两个职责拆得很开:步骤new 表达式 (n…...

Python大模型微调框架选型决策树(2024权威Benchmark实测TOP5框架吞吐/显存/收敛性对比)

更多请点击: https://intelliparadigm.com 第一章:Python大模型本地微调框架选型决策树总览 在资源受限的本地环境中开展大语言模型微调,框架选型直接决定训练可行性、显存效率与工程可维护性。当前主流开源方案在量化支持、LoRA/QLoRA集成度…...

如何快速配置HS2-HF_Patch:游戏增强补丁完整指南

如何快速配置HS2-HF_Patch:游戏增强补丁完整指南 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 你是否厌倦了日文原版Honey Select 2的游戏体验&am…...

告别僵硬动画!用UE5.1的IK重定向器,5分钟让你的自定义角色“活”起来

告别僵硬动画!用UE5.1的IK重定向器,5分钟让你的自定义角色“活”起来 在游戏开发或影视动画制作中,一个精心设计的角色模型如果只能僵硬地站立,就像一尊没有灵魂的雕塑。传统动画制作流程往往需要美术师逐帧调整,耗时耗…...

收藏级|2026最新大模型应用开发学习指南(小白/程序员必看,转行避坑直达面试)

对于程序员和想入行AI的小白来说,2026年的行业共识愈发清晰:AI赛道不可逆,而Agent作为当前大模型应用的核心爆发点,早已成为就业市场的“香饽饽”——掌握Agent开发技能,无论是转岗AI、薪资翻倍,还是提升自…...

终极游戏资源编辑指南:用ExtractorSharp轻松制作DNF补丁

终极游戏资源编辑指南:用ExtractorSharp轻松制作DNF补丁 【免费下载链接】ExtractorSharp Game Resources Editor 项目地址: https://gitcode.com/gh_mirrors/ex/ExtractorSharp ExtractorSharp是一款功能强大的游戏资源编辑器,专门为游戏MOD爱好…...

用Java正则表达式搞定L1-064‘估值一亿的AI核心代码’:从字符串处理到AI对话模拟

用Java正则表达式解析AI对话逻辑:从字符串处理到智能应答模拟 在算法竞赛和实际开发中,字符串处理往往是绕不开的难题。PTA平台上的L1-064题"估值一亿的AI核心代码"就是一个典型例子——它要求我们将原始输入转换为符合特定规则的AI应答。这道…...

4G无线串口对传模块:RS232/485通讯,工业现场便捷组网

4G无线串口对传模块是一类工业级无线通信设备,实现两台或多台设备之间串口数据的远程、透明无线传输。使用时通常成对出现,一端接A设备,另一端接B设备,配对后就能让它们像用串口线直接连接一样,互相收发数据。一、功能…...

Spring Boot多租户实战指南(Tenant-Aware DataSource深度剖析)

更多请点击: https://intelliparadigm.com 第一章:Java 多租户数据安全隔离 在云原生与 SaaS 架构普及的背景下,Java 应用实现多租户(Multi-tenancy)已成为常态。数据安全隔离是其核心挑战——必须确保租户 A 无法访…...

告别龟速下载!PyCharm里配置Python库的5种方法实测(含阿里云/清华源对比)

PyCharm高效配置Python库的终极指南:5种方法深度评测与实战技巧 每次在PyCharm里安装Python库时,进度条像蜗牛一样缓慢移动,你是否也经历过这种煎熬?作为Python开发者,我们每天都要与各种第三方库打交道,但…...

告别繁琐!用ApkInfoQuick快速提取APK关键信息

我开发了一个开源 APK 信息查看工具:ApkInfoQuick 最近我做了一个小工具,名字叫 ApkInfoQuick。 它是一个面向 Android APK 文件的信息查看与解析工具,支持桌面 GUI,也支持 CLI 命令行。项目已经准备开源放到 GitHub 上&#xff0…...

智能图片去重工具AntiDupl.NET:4大核心模块高效释放存储空间终极指南

智能图片去重工具AntiDupl.NET:4大核心模块高效释放存储空间终极指南 【免费下载链接】AntiDupl A program to search similar and defect pictures on the disk 项目地址: https://gitcode.com/gh_mirrors/an/AntiDupl 你是否经常面临手机相册被重复照片塞满…...

告别VL31N手工操作:用ABAP脚本批量创建内向交货单的自动化实践

告别VL31N手工操作:用ABAP脚本批量创建内向交货单的自动化实践 每天早晨,当SAP SD模块的业务员小王打开VL31N事务码准备处理采购到货时,总会被几十个待创建的交货单淹没。重复输入采购订单号、核对物料信息、点击保存——这样的机械操作不仅耗…...

抖音视频批量下载终极指南:4步打造你的专属内容库

抖音视频批量下载终极指南:4步打造你的专属内容库 【免费下载链接】douyin-downloader A practical Douyin downloader for both single-item and profile batch downloads, with progress display, retries, SQLite deduplication, and browser fallback support. …...

GHelper完整指南:3步轻松掌控华硕笔记本性能与续航

GHelper完整指南:3步轻松掌控华硕笔记本性能与续航 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, Scar,…...

MAXIM美信 MAX30101EFD+T OLGA14 心率传感器

优势与特性 LED反射式心率监测器和脉搏血氧传感器 小巧的5.6mmx3.3mmx1.55mm 14引|脚光学模块集成盖板玻璃,实现最佳、稳健性能 移动设备超低功耗运行 可编程采样率和LED电流以节省电源 低功耗心率监测器(小于1毫瓦)超低关断电流(典型值0.7uA) 快速数据输出能力 高采…...

手机号查询QQ号完整指南:3分钟找回遗忘账号的终极解决方案

手机号查询QQ号完整指南:3分钟找回遗忘账号的终极解决方案 【免费下载链接】phone2qq 项目地址: https://gitcode.com/gh_mirrors/ph/phone2qq 你是否曾因忘记QQ号而无法登录重要账号?或者更换手机后,只记得手机号却找不到对应的QQ账…...

别再只用2D地图了!手把手教你用Vue3+ECharts GL打造可交互的3D中国地图(附完整代码和天空盒资源)

突破平面边界:用Vue3与ECharts GL构建沉浸式3D地理可视化方案 当数据可视化遇上三维空间,地图不再只是冰冷的平面轮廓。想象一下,你的用户可以通过鼠标拖拽360度旋转查看地形起伏,点击省份时区域会动态凸起响应,飞鱼线…...

生图新王GPT Image 2正式发布!彻底告别中文乱码,附无魔法国内稳定渠道

AI绘图圈又迎来了史诗级大地震!出乎所有人意料,OpenAI这次连发布会都没开,GPT-Image-2 就已经全量开放测试了。 目前,所有用户均可免费体验,但无论是免费用户还是付费用户,都会面临严格的额度限制。免费用…...

戴尔笔记本风扇终极管理指南:免费开源智能散热解决方案

戴尔笔记本风扇终极管理指南:免费开源智能散热解决方案 【免费下载链接】DellFanManagement A suite of tools for managing the fans in many Dell laptops. 项目地址: https://gitcode.com/gh_mirrors/de/DellFanManagement 你是否曾因戴尔笔记本风扇噪音过…...

期刊推荐:Journal of Artificial Intelligence and Soft Computing Research(ISSN: 2083-2567)

学科领域: 计算机-人工智能 期刊类型: SCI/SSCI/AHCI 收录数据库: SCI(SCIE) ISSN: 2083-2567 中科院: 2区 影响因子: 2.4 JCR: Q3 咨询获取专业投稿服务 Journal of Artificial Intelli…...

ImageGlass:Windows平台终极开源图像浏览解决方案,高效支持90+格式

ImageGlass:Windows平台终极开源图像浏览解决方案,高效支持90格式 【免费下载链接】ImageGlass 🏞 A lightweight, versatile image viewer 项目地址: https://gitcode.com/gh_mirrors/im/ImageGlass 在数字图像处理日益普及的今天&am…...

智能制造系统推广的核心的十个关键问题

推广智能制造系统(尤其是迈向资产共生阶段)时,不能只关注设备买入,急须解决以下十个关乎“成败”的核心问题:数据孤岛与协议兼容问题:底层设备品牌庞杂(Fanuc, Siemens, Omron 等)&a…...

Linux下Intel AX101 WiFi 6驱动问题解决方案

1. 问题背景:Alder Lake-N迷你主机在Linux下的WiFi 6兼容性问题最近搭载Intel Alder Lake-N处理器(如N95、N100、Core i3-N300/N305)的迷你主机因其出色的性价比受到广泛关注。这类设备通常配备Intel AX101无线模块,支持WiFi 6&am…...

Git误提交恢复

先执行语句: git reset --mixed HEAD~1add了,也commit了,发现crmeb.zip忘记删除,这个文件不用提交实际执行语句...

别再乱刷了!手把手教你读懂Android卡刷包里的updater-script脚本(附权限设置详解)

深度解析Android卡刷包:从updater-script脚本到安全刷机实践 在Android设备刷机过程中,updater-script脚本扮演着至关重要的角色。这个看似简单的文本文件实际上控制着整个刷机流程的每一个细节操作。对于想要深入了解刷机原理或自行定制ROM的用户来说&a…...

FPGA工程师的JESD204B通关指南:从Subclass1链路建立到调试避坑(附Xilinx/Intel IP核使用心得)

FPGA工程师的JESD204B实战指南:从参数配置到链路调试全解析 在高速数据采集与处理系统中,JESD204B接口已成为连接FPGA与高速ADC/DAC的事实标准。这个看似简单的串行接口背后,却隐藏着复杂的配置参数和严格的时序要求。作为FPGA工程师&#xf…...

串口调试工具:功能强大的Modbus协议支持工具

项目概述 串口调试工具是一款功能丰富、界面友好的串口通信调试软件,专为嵌入式开发、工业控制和物联网设备调试而设计。该工具不仅支持基本的串口通信功能,还集成了Modbus协议生成功能,能够帮助开发者快速构建和测试Modbus通信。 主要特点 支…...

Windows Subsystem for Linux (WSL) 运行 Firefox 浏览器时遇到中文乱码的解决方法

在使用Windows Subsystem for Linux (WSL) 运行 Firefox 浏览器时,有时会遇到中文乱码的问题。这通常是由于字体支持或字符编码设置不正确导致的。以下是一些解决此问题的步骤:1. 确保系统字体支持中文首先,确保你的WSL发行版安装了支持中文的…...

你的ST-LINK是‘李鬼’吗?实测Keil中关闭一个选项,破解‘非正版设备’警告(附原理浅析)

ST-LINK设备真伪检测机制解析与Keil警告消除方案 最近在嵌入式开发社区中,关于"Not a genuine ST Device! Abort connection"警告的讨论热度持续攀升。许多开发者在使用第三方ST-LINK调试器时都会遇到这个恼人的提示,虽然不影响基本功能&#…...