C++ operator new和new区别 C++内存分配与构造函数调用分离【深度】
发布时间 - 2026-01-24 00:00:00 点击率:次operator new仅分配内存而不调用构造函数,必须配合placement new或new表达式(自动调用构造)使用;其重载需配对实现operator delete,且数组形式须分别重载operator new[]/delete[]。
operator new 只分配内存,不调用构造函数
operator new 是一个纯内存分配函数,行为上等价于 C 的 malloc:它只向系统申请原始字节空间,返回 void*,完全不涉及类型信息或对象生命周期。你不能直接用它创建可用的对象实例——哪怕类有默认构造函数,它也绝不会被调用。
常见错误是误以为 operator new(sizeof(MyClass)) 能得到一个已构造的 MyClass 对象,结果后续直接调用成员函数就会崩溃(未定义行为,通常因 this 指针指向未初始化内存)。
- 典型使用场景:配合
placement new实现自定义对象布局,比如内存池、对象数组预分配、序列化反序列化时跳过构造 - 它可被重载:类内声明
static void* operator new(size_t)会覆盖全局版本;重载时必须返回非空指针,否则抛std::bad_alloc - 注意:
operator new[]和operator delete[]必须成对重载,否则new T[N]行为不可靠
new 表达式 = operator new + 构造函数调用
当你写 new MyClass(1, 2),编译器实际拆成两步:先调用 operator new(sizeof(MyClass)) 分配内存,再在该地址上调用 MyClass::MyClass(1, 2)。这两步不可分割,且构造失败时会自动调用匹配的 operator delete(不是 delete)回滚内存。
这解释了为什么自定义 opera 抛异常后,
new 表达式仍能保证强异常安全:构造函数若 throw,编译器插入的清理代码会调用你重载的 operator delete(前提是签名匹配)。
- 如果类重载了
operator new但没提供对应operator delete,构造异常时可能内存泄漏 -
new (std::nothrow) MyClass不影响构造函数调用,只是让第一步operator new失败时返回nullptr而非抛异常 - 数组形式
new MyClass[10]调用的是operator new[](size_t),不是operator new
placement new 是唯一合法的“只构造不分配”方式
标准库提供的 operator new(std::size_t, void* p)(即 placement new)不分配内存,只返回传入的 p。它存在的唯一目的,就是在已知地址上显式调用构造函数:
char buffer[sizeof(MyClass)]; MyClass* obj = new (buffer) MyClass(42); // 在 buffer 上构造
这里 new (buffer) 是语法糖,底层就是调用 MyClass::MyClass(42),buffer 必须足够大且对齐正确(可用 alignas(MyClass) 保证)。
- 必须手动调用析构函数:
obj->~MyClass(),否则资源泄漏 - 不能用
delete obj销毁它——因为没用operator new分配,delete会尝试调用operator delete去释放非法地址 - 自定义 placement new(如带额外参数)需自行声明,编译器不自动识别;标准 placement new 不抛异常,也不检查
p是否为空
operator delete 和 delete 表达式的对应关系容易混淆
delete ptr 表达式也分两步:先调用对象的析构函数,再调用 operator delete(ptr) 释放内存。关键点在于:它调用的 operator delete 版本,由与之配对的 new 表达式所用的 operator new 决定。
例如:new (std::nothrow) T 分配的内存,必须用 delete(而非 delete nothrow)销毁;而 new T 分配的,若用 delete 但类只重载了 operator delete(void*, std::nothrow_t),则链接失败或调用错误版本。
- 全局
operator delete(void*)是所有普通new的兜底释放函数;若类重载了它,delete就调用类版本 - 数组删除
delete[] ptr必须匹配operator new[],否则未定义行为(常见 crash 点) - 自定义
operator delete应声明为noexcept,否则析构后释放失败可能导致程序终止
C++ 的内存分配和对象构造从设计上就是解耦的,但这种解耦只在你明确需要控制时才有价值。多数情况下,直接用 new 和 delete 就够了;一旦开始重载 operator new 或用 placement new,就必须同步处理所有配套的 delete 和析构逻辑——漏掉任意一环,问题往往延迟到运行时才暴露。
# 字节
# c++
# nas
# 区别
# 标准库
# 为什么
# Static
# 成员函数
# 构造函数
# 析构函数
# throw
# void
# 指针
# operator
# 空指针
# delete
# 对象
# this
# 自定义
# 而非
# 两步
# 时才
# 的是
# 是一个
# 不分配
# 就会
# 也不
# 序列化
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
香港服务器网站推广:SEO优化与外贸独立站搭建策略
javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】
关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
JavaScript Ajax实现异步通信
北京的网站制作公司有哪些,哪个视频网站最好?
如何快速查询网址的建站时间与历史轨迹?
网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?
详解Huffman编码算法之Java实现
千库网官网入口推荐 千库网设计创意平台入口
CSS3怎么给轮播图加过渡动画_transition加transform实现【技巧】
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
如何用花生壳三步快速搭建专属网站?
国美网站制作流程,国美电器蒸汽鍋怎么用官方网站?
晋江文学城电脑版官网 晋江文学城网页版直接进入
laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法
北京专业网站制作设计师招聘,北京白云观官方网站?
如何在IIS7中新建站点?详细步骤解析
新三国志曹操传主线渭水交兵攻略
高防服务器租用指南:配置选择与快速部署攻略
原生JS实现图片轮播切换效果
Laravel怎么清理缓存_Laravel optimize clear命令详解
如何快速启动建站代理加盟业务?
如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)
Laravel怎么调用外部API_Laravel Http Client客户端使用
PHP 实现电台节目表的智能时间匹配与今日/明日轮播逻辑
Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】
如何快速查询网站的真实建站时间?
Laravel如何实现一对一模型关联?(Eloquent示例)
Laravel如何处理跨站请求伪造(CSRF)保护_Laravel表单安全机制与令牌校验
js代码实现下拉菜单【推荐】
UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】
如何在腾讯云免费申请建站?
Laravel DB事务怎么使用_Laravel数据库事务回滚操作
Python自然语言搜索引擎项目教程_倒排索引查询优化案例
郑州企业网站制作公司,郑州招聘网站有哪些?
Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】
音响网站制作视频教程,隆霸音响官方网站?
Laravel Telescope怎么调试_使用Laravel Telescope进行应用监控与调试
Laravel如何升级到最新版本?(升级指南和步骤)
如何在建站主机中优化服务器配置?
如何正确下载安装西数主机建站助手?
zabbix利用python脚本发送报警邮件的方法
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
动图在线制作网站有哪些,滑动动图图集怎么做?
深圳网站制作平台,深圳市做网站好的公司有哪些?
宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法
香港服务器如何优化才能显著提升网站加载速度?

