C++ new 操作的背后都经历了什么?
[TOC](C new 操作的背后都经历了什么)!-- 顶部锚点 --br/table width100%trtd width50%div idtop aligncenterfont faceSTCAIYUN colorred size4emThe Begin点点关注收藏不迷路em/font/divbrdiv aligncenter stylemargin: 20px 0;a href#bottom styledisplay: inline-block; padding: 12px 35px; background: #0a0a0a; border: 2px solid #00ff88; border-radius: 8px; text-decoration: none; box-shadow: 0 0 15px rgba(0,255,136,0.5); transition: all 0.3s;font faceSTCAIYUN color#08979D size4 stylefont-weight: bold; letter-spacing: 2px;⬇ ⬇ 底部 ⬇ ⬇/font/a/div/td/tr/table1. 引言从一条语句到内存的旅程在 C 中我们经常写这样的代码int* p new int(42); MyClass* obj new MyClass();这条看似简单的new语句背后却隐藏着一条漫长而复杂的链路内存分配、类型转换、构造函数调用、异常处理…… 它远不止是malloc加一层包装那么简单。本文将深入剖析 C 中new操作的完整生命周期从编译器视角到操作系统底层带你一探new背后的全貌。---2. new 操作的本质分层一个完整的new表达式 (new expression) 可以拆解为三个层次| 层次 | 概念 | 职责 ||------|------|------|| 上层 |new 表达式(new expression) | 程序员写的new T由编译器负责翻译 || 中层 |operator new函数 | 负责原始内存的分配可重载 || 下层 |底层内存分配器(allocator) | 如malloc、HeapAlloc或自定义分配器 |它们的关系如下new T(args...) -- 调用 operator new 分配原始内存 -- 在内存上构造对象 (placement new) -- 返回指针---3. 第一步new 表达式的编译展开当我们写下new MyClass(10)时编译器会将其翻译为类似以下的伪代码// 伪代码展示编译器行为 void* raw_mem operator new(sizeof(MyClass)); // 1. 分配原始内存 if (raw_mem nullptr) { // 如果 operator new 抛异常则不会执行构造 } MyClass* ptr nullptr; try { ptr new (raw_mem) MyClass(10); // 2. placement new 调用构造函数 } catch (...) { operator delete(raw_mem); // 3. 构造失败则释放内存 throw; // 4. 重新抛出异常 } return ptr;编译器至少做了四件事调用operator new获取原始内存。在原始内存上调用构造函数 (通过 placement new)。如果构造函数抛出异常自动调用operator delete释放已分配的内存。返回构造好的对象指针。---4. 第二步operator new 函数operator new是 C 标准库中定义的全局函数负责分配原始内存不构造对象。它的典型声明是void* operator new(std::size_t size); // 普通版本 void* operator new(std::size_t size, std::nothrow_t) noexcept; // nothrow 版本4.1 默认实现标准库的默认operator new内部通常调用malloc并在失败时抛出std::bad_alloc异常。// glibc 简化示意 void* operator new(std::size_t size) { if (size 0) size 1; // C 标准要求即使 size0 也返回合法指针 void* ptr malloc(size); if (!ptr) { throw std::bad_alloc(); // 失败抛异常 } return ptr; }4.2 可重载性operator new可以被全局重载也可以在类内部重载用于实现自定义内存管理如内存池、对象池。class MyClass { public: static void* operator new(std::size_t size) { std::cout Custom new for MyClass, size size std::endl; return ::operator new(size); // 仍可回退到全局 } static void operator delete(void* ptr) { ::operator delete(ptr); } };4.3 带额外参数的 placement new标准库还提供了带额外参数的 placement new 版本最常见的是new (void*)用于在已分配的内存上构造对象。void* buffer malloc(sizeof(MyClass)); MyClass* obj new (buffer) MyClass(); // 在 buffer 位置构造对象 // 必须手动调用析构函数 obj-~MyClass(); free(buffer);你也可以自定义自己的 placement new 版本例如new (arena, 0)这种。---5. 第三步内存分配器底层operator new默认调用malloc但malloc本身也不是直接向操作系统申请内存的。现代 C/C 运行库的内存分配器 (如 glibc 的 ptmalloc2、tcmalloc、jemalloc) 通常采用以下策略| 内存大小 | 分配策略 ||----------|----------|| 小对象 ( 64KB) | 从线程本地缓存或空闲链表中复用避免频繁系统调用 || 大对象 ( 64KB) | 直接通过mmap向 OS 申请匿名内存页 |这种分层设计极大提升了小对象频繁分配/释放的性能。最终当分配器向操作系统申请内存时会通过系统调用Linuxbrk/sbrk(堆扩展) 或mmap(匿名映射)WindowsHeapAlloc/VirtualAlloc---6. 第四步对象构造 (Constructor)内存分配完成后接下来是调用构造函数。这一步通过placement new实现编译器会在目标内存地址上直接调用构造函数。// 等价于编译器生成的代码 new (raw_mem) MyClass(10);注意构造函数可以抛出异常。如果构造过程中抛出异常operator new已经分配的内存需要被释放否则会造成内存泄漏。这就是为什么前面编译器生成的伪代码中有try-catch结构保证异常安全。---7. 第五步数组 new (new[])当我们写new MyClass[10]时过程略有不同调用operator new[]分配内存默认也是调用operator new。对于有非平凡构造函数的类编译器会在数组头部额外存储数组长度以便在delete[]时知道需要调用多少次析构函数。依次对每个元素调用默认构造函数或初始化器。// 编译器对 new[] 的展开示意 void* raw operator new[](sizeof(MyClass) * count extra_bytes); // 在头部存储 count size_t* header static_castsize_t*(raw); *header count; MyClass* data static_castMyClass*(raw extra_bytes); for (size_t i 0; i count; i) { new (data i) MyClass(); // 依次构造 }---8. 内存释放与析构delete 的对称过程delete操作正好是new的逆过程调用对象的析构函数 (如果是数组则按逆序调用所有元素的析构函数)。调用operator delete(或operator delete[]) 释放原始内存。operator delete默认调用free归还内存给分配器。// delete ptr 的伪代码 if (ptr ! nullptr) { ptr-~MyClass(); // 1. 调用析构 operator delete(ptr); // 2. 释放内存 }重要delete和free绝对不能混用用new分配的内存必须用delete用malloc分配的内存必须用free。---9. 完整流程图否是是否new T(args)计算所需字节数 (可能包含对齐/数组头部)调用 operator new(size_t)operator new 调用底层分配器 (如 malloc)底层分配器: 线程缓存 / 空闲链表 / mmap/brk从 OS 获取虚拟内存 (物理页按需映射)返回原始内存指针 raw内存分配成功?抛出 std::bad_alloc结束 (异常)在 raw 上执行 placement new调用构造函数 T::T(args)构造是否抛出异常?operator delete(raw) 释放内存重新抛出异常返回类型化的指针 T*结束 (正常)---10. 特殊情况与进阶话题10.1 nothrow new使用std::nothrow版本分配失败时返回nullptr而不是抛出异常int* p new (std::nothrow) int[1000]; if (p nullptr) { // 处理分配失败 }10.2 自定义 new 处理函数 (new_handler)可以通过std::set_new_handler设置一个全局回调函数当operator new分配失败时在抛出异常前会反复调用此函数给你机会释放内存或重试。void my_handler() { std::cerr Out of memory! Trying to release...\n; // 尝试释放一些缓存 } std::set_new_handler(my_handler);10.3 内存对齐对于需要特定对齐的类型 (如alignas(64)的类)operator new需要返回对齐的地址。C17 引入了operator new的对齐版本void* operator new(std::size_t size, std::align_val_t alignment);10.4 new 与构造函数中的 virtual 函数在构造函数中调用虚函数不会发生多态因为派生类尚未构造完成。这虽然是语法允许的但属于设计上需要避免的反模式。---11. 总结new 的完整链路| 步骤 | 操作 | 执行者 | 可自定义? ||------|------|--------|-----------|| 1 | 解析 new 表达式计算大小 | 编译器 | ❌ || 2 | 调用operator new| 编译器插入 | ✅ (可重载) || 3 | 底层内存分配 (malloc/mmap) | 标准库/OS | ✅ (可替换分配器) || 4 | 内存对齐和填充 | 分配器 | ❌ || 5 | 调用构造函数 (placement new) | 编译器 | ❌ || 6 | 异常时自动回收内存 | 编译器 | ❌ || 7 | 返回指针 | - | ❌ |snew的每一次调用都是编译器、运行库、操作系统三者紧密协作的结果。理解这条链路不仅有助于写出更高效的内存管理代码也能在遇到内存泄漏、异常安全、性能瓶颈等问题时做到心中有数、定位准确。---!-- 底部锚点 --br/table width100%trtd width50%div aligncenterfont faceSTCAIYUN colorred size4emThe End点点关注收藏不迷路em/font/divbrdiv idbottom aligncenter stylemargin: 20px 0;a href#top styledisplay: inline-block; padding: 12px 35px; background: #0a0a0a; border: 2px solid #00ff88; border-radius: 8px; text-decoration: none; box-shadow: 0 0 15px rgba(0,255,136,0.5); transition: all 0.3s;font faceSTCAIYUN color#08979D size4 stylefont-weight: bold; letter-spacing: 2px;⬆ ⬆ 顶部 ⬆ ⬆/font/a/div/td/tr/table

相关新闻

Unity相机与交互系统实战:飞行、路径、晃动相机及触摸控制

Unity相机与交互系统实战:飞行、路径、晃动相机及触摸控制

1. 项目概述:从单一交互到沉浸式体验的构建 在Unity项目开发中,尤其是涉及到3D展示、产品演示、数字孪生或游戏场景时,如何让用户与虚拟世界进行自然、流畅且富有表现力的交互,是提升体验的关键。一个静态的、只能平移缩放旋转的相…

2026/8/18 9:34:57 阅读更多 →
大语言模型文本长度限制:技术原理与工程优化实践

大语言模型文本长度限制:技术原理与工程优化实践

这次我们来看一个关于大语言模型(LLMs)与文本长度限制的技术话题——"LLMs and the Curse of the Word Count"。这个标题直指大语言模型在处理长文本时面临的核心挑战:随着输入文本长度的增加,模型性能如何变化&#xf…

2026/8/18 9:36:11 阅读更多 →
深入浅出华为S7700交换机接口管理:从MTU玄学到配置实战,一篇搞定

深入浅出华为S7700交换机接口管理:从MTU玄学到配置实战,一篇搞定

[TOC](深入浅出华为S7700交换机接口管理&#xff1a;从MTU玄学到配置实战&#xff0c;一篇搞定)<!-- 顶部锚点 --> <br/> <table width"100%"><tr><td width"50%"><div id"top" align"center">&l…

2026/8/17 10:21:08 阅读更多 →

最新新闻

7DGroup 开源 dsh-skill-7d-git-commit 插件

7DGroup 开源 dsh-skill-7d-git-commit 插件

文章目录项目信息功能特性项目结构快速开始通过 dsh CLI 安装在 dsh 会话中安装&#xff08;推荐&#xff09;构建与测试使用方式提交规范与 GitLab 集成使用集成功能说明背景&#xff1a;为什么要做提交信息校验设计原理&#xff1a;选择 pre-receive 阶段拦截工作原理实践落地…

2026/8/18 10:01:45 阅读更多 →
从零添加你的第一个游戏:Sunshine 应用管理完整指南

从零添加你的第一个游戏:Sunshine 应用管理完整指南

从零添加你的第一个游戏&#xff1a;Sunshine 应用管理完整指南 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你打开 Sunshine 的 Web 界面&#xff0c;满怀期待地准备串流昨晚刚…

2026/8/18 10:01:45 阅读更多 →
Java企业AI转型实战:技术栈重构与典型场景落地

Java企业AI转型实战:技术栈重构与典型场景落地

1. Java企业向AI应用开发转型的必然性 当ChatGPT引爆全球AI热潮时&#xff0c;许多Java工程师还在纠结Spring Boot的自动配置原理。直到有一天&#xff0c;公司CTO在全员会议上宣布&#xff1a;"明年所有产品线必须接入AI能力"&#xff0c;我才猛然意识到——这个曾经…

2026/8/18 10:01:45 阅读更多 →
每天1小时 vs 10分钟:游戏自动化工具三月七小助手如何重写星穹铁道的夜晚

每天1小时 vs 10分钟:游戏自动化工具三月七小助手如何重写星穹铁道的夜晚

每天1小时 vs 10分钟&#xff1a;游戏自动化工具三月七小助手如何重写星穹铁道的夜晚 【免费下载链接】March7thAssistant 崩坏&#xff1a;星穹铁道全自动 三月七小助手 项目地址: https://gitcode.com/gh_mirrors/ma/March7thAssistant 下班后瘫在沙发上打开《崩坏&am…

2026/8/18 10:01:45 阅读更多 →
OBS多平台直播终极指南:免费插件obs-multi-rtmp三步带你同时开播

OBS多平台直播终极指南:免费插件obs-multi-rtmp三步带你同时开播

OBS多平台直播终极指南&#xff1a;免费插件obs-multi-rtmp三步带你同时开播 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 你是不是也有这样的经历&#xff1a;明明是一个直播间的内容…

2026/8/18 10:01:45 阅读更多 →
RocketMQ 5.5.0 Docker 部署踩坑实录

RocketMQ 5.5.0 Docker 部署踩坑实录

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;「历代文学网」&#xff08;PC端可以访问&#xff1a;https://lidaiwenxue.com/#/?__c1000&#xff0c;移动端可关注公众号 “ 心海云图 ” 微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;首席架构师…

2026/8/18 10:00:45 阅读更多 →

日新闻

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图:用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF

告别逐帧截图&#xff1a;用 extract-video-ppt 快速提取视频中的 PPT 并一键导出 PDF 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 如果你还停留在"看网课 不停暂停 截图 …

2026/8/18 0:00:57 阅读更多 →
思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手:7个字重免费商用,从下载到上线的完整走查

思源宋体TTF一站式上手&#xff1a;7个字重免费商用&#xff0c;从下载到上线的完整走查 【免费下载链接】source-han-serif-ttf Source Han Serif TTF 项目地址: https://gitcode.com/gh_mirrors/so/source-han-serif-ttf 你是不是也经历过这种时刻&#xff1a;设计稿里…

2026/8/18 0:00:58 阅读更多 →
华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南:GHelper 如何用一个 10MB 文件替代 Armoury Crate

华硕笔记本控制权回收指南&#xff1a;GHelper 如何用一个 10MB 文件替代 Armoury Crate 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, …

2026/8/18 0:00:59 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者&#xff0c;最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent&#xff0c;从本地部署到云端API&#xff0c;我们正处在一个技术栈快速重构的节点。然而&#xff0c;面对层出不穷的模型、框架和工具&#xf…

2026/8/18 9:15:35 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/18 9:06:28 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。&#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室&#x1f447; 关注我领取海量matlab电子书和…

2026/8/18 9:04:56 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/17 18:54:37 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/17 18:55:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/17 18:55:55 阅读更多 →