Placement new、operator new、new operator 完全释疑

c++ 源码 之 标准库new , operator new , placement new , array new 在c++中管理内存的一些手段与细节 那么这篇博客的内容主要是在学习了jjhou老师的内存管理后我自己总结的一些知识点,关于侯捷老师的内存管理的内容可以自己搜索那么直接进入正题了 1.new和operator new 依照bjarne的c++ programming language的11.2.3章节所说,new ,delete,operator new,operator delete... 阅读详情

Placement new、operator new、new operator 完全释疑

 

首先我们区分下几个容易混淆的关键词:

      new(也称作new operator)、operator new、placement new。看如下代码:

   1: class MyClass {...}; 
   2: MyClass *p = new MyClass; 

这里的new是上述三个关键字中的第一个,成为new操作符。实际上它执行如下3个过程:

1. 调用operator new分配内存

2. 调用构造函数生成类对象

3. 返回相应指针

      placement new 是重载operator new的一个标准、全局的版本。它不能被自定义的版本代替(不像普通的operator new和operator delete能够被替换成用户自定义的版本)。它的原型如下:

1void *operator new( size_t, void *p ) throw()  { return p; }

       new和delete操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的。要实现不同的内存分配行为,需要重载operator new和operator delete,而不是new和delete。

      operator new就像operator+一样,是可以重载的。但是不能在全局对原型为void operator new(size_t size)这个原型进行重载,一般只能在类中进行重载。如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分配。同理,operator new[]、operator delete、operator delete[]也是可以重载的。

      至于placement new,只是operator new的一个重载的版本,只是我们很少用到它。如果你想在已经分配的内存中创建一个对象,使用new时行不通的。也就是说placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。

      我们知道使用new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。placement new就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存,内存分配的时间是常数。而且不会出现在程序运行中途出现内存不足的异常。所以,placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序。 placement new使用方法如下:

1. 缓冲区提前分配,可以使用堆的空间,也可以使用栈的空间。所以分配方式有如下两种:

1class MyClass {…}; 
2char *buf=new char[N*sizeof(MyClass)+sizeof(int)];
3char buf[N*sizeof(MyClass)+sizeof(int)];

2. 对象的构造

1MyClass * pClass=new(buf) MyClass; //使用placement new

3. 对象的销毁
      一旦这个对象使用完毕,你必须显式的调用类的析构函数进行销毁对象。但此时内存空间不会被释放,以便其他的对象的构造。

1pClass->~MyClass();

4. 内存的释放
      如果缓冲区在堆中,那么调用delete[] buf 进行内存的释放。如果在栈中,那么在其作用域内有效,跳出作用域,内存自动释放。

注意:

      在C++标准中,对于placement operator new []有如下的说明: placement operator new[] needs implementation-defined amount of additional storage to save a size of array。所以我们必须申请比原始对象大小多出sizeof(int)个字节来存放对象的个数,或者说数组的大小。
      使用方法第二步中的new才是使用placement new,其实是没有申请内存的,只是调用了构造函数。返回一个指向已经分配好的内存的一个指针,所以对象销毁的时候不需要调用delete释放空间,但必须调用析构函数销毁对象。

参考自:http://www.ksarea.com/articles/20080124_cc.html

 

以上为网友整理的资料。下面为一个C++权威参考资料:

      operator new分为三种形式(前2种不调用构造函数,这点区别于new operator):

   1: void* operator new (std::size_t size) throw (std::bad_alloc);
   2: void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw();
   3: void* operator new (std::size_t size, void* ptr) throw();

      第一种分配size个字节的存储空间,并进行对象类型进行内存对齐。如果成功,返回一个非空的指针指向首地址。失败抛出bad_alloc异常。

      第二种在分配失败时不抛出异常,它返回一个NULL指针。

      第三种是placement new版本。它不分配内存,调用合适的构造函数在ptr所指的地方构造一个对象,之后返回实参指针ptr。

      三种版本的operator new 定义在全局命名空间,不在std中。第一、第二个版本C++默认在每个编译单元中声明,不需要#include <new>头文件。第一、第二个版本可以被用户更换和重载,定义自己的版本,第三种placement new不可重载。

例子:

01// operator new example
02#include <iostream>
03#include <new>
04using namespace std;
05  
06struct myclass {myclass() {cout <<"myclass constructed/n";}};
07  
08int main () {
09  
10   int * p1 = new int;
11// same as:
12// int * p1 = (int*) operator new (sizeof(int));
13  
14   int * p2 = new (nothrow) int;
15// same as:
16// int * p2 = (int*) operator new (sizeof(int),nothrow);
17  
18   myclass * p3 = (myclass*) operator new (sizeof(myclass));
19// (!) not the same as:
20// myclass * p3 = new myclass;
21// (constructor not called by function call, even for non-POD types)
22  
23   new (p3) myclass;   // calls constructor
24// same as:
25// operator new (sizeof(myclass),p3)
26  
27   return 0;
28}

输出:myclass constructed

重载operator new    

01class Base {
02public:
03  Base() { }
04 
05  void *operator new( size_t size, string str ) {
06    cout << "Logging an allocation of " << size << " bytes for new object'" << str << "'" << endl;
07    return malloc( size );
08  }
09 
10  int var;
11  double var2;
12};
13 
14...
15 
16Base* b = new ("Base instance 1") Base;

      输出: Logging an allocation of 12 bytes for new object 'Base instance 1'

 

new operator的四种用法

1pointer = new type;
2pointer = new type( initializer );
3pointer = new type[size];
4pointer = new( arg-list ) type...    //4th vision
5 
6Foo *foo; 
7foo = new(nothrow) Foo();            //use the 4th vision
8assert( foo );

      其中,nothrow为 C++预定义的std::nothrow_t类型全局常量。

 

我的理解

      operator new可以被重载,它的三个版本本质上是函数,它们只分配空间,不调用构造函数。而new、delete(也叫做new operator、delete operator)不可被重载,它们是运算符,分配空间,并且调用构造函数。

 

相关参考:

http://blog.youkuaiyun.com/selooloo/archive/2010/06/12/5667176.aspx

http://hi.baidu.com/%C7%C6%C0%B4%C7%C3%C8%A5/blog/item/99821106f9d3abc47b8947b9.html

 

【C++内存管理机制】学习笔记(3):replacement new Hello!ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!唯有努力💪本文仅记录自己感兴趣的内容文章仅作为个人学习笔记记录,记录从0到1的一个过程希望对您有一点点帮助,如有错误欢迎小伙伴指正。 阅读详情

相关推荐

工程师必看:如何用定时截尾试验快速验证产品MTBF(附真实案例解析)

本文为硬件工程师详细解析了如何运用定时截尾试验快速验证产品MTBF(平均无故障工作时间)。通过七步实战法,结合工业物联网网关的真实案例,阐述了从参数设定、试验执行到结果判读的完整流程,并提供了MATLAB脚本实现自动化计算与可视化,帮助工程师在有限时间内科学评估产品可靠性。

weixin_29243063的博客 493

C++——new,delete,与placement new。

介绍new和delete原理、用法、常见错误、介绍定位new

chfens的博客 755

Proteus仿真实战:用AT89C51+L298N搭建直流电机PID调速系统(附完整工程文件)

本文详细介绍了使用Proteus仿真平台结合AT89C51单片机和L298N驱动模块搭建直流电机PID闭环调速系统的全过程。从硬件选型、电路连接到PID算法实现与参数整定,提供了完整的开发指南和工程文件,帮助读者快速掌握闭环调速系统的设计与调试技巧。

weixin_28724661的博客 448

c++ replacement new 操作

#include #include #include //注意必须包括此头文件 class CTest { public: CTest(int i,int ii) { m = i; n = ii; p = new char[100]; strcpy(p,"good test"); } ~CTest() { m = 11; n = 13; delete[

qingshuiaishui的专栏 2709

提升仿真效率:Synopsys VCS高级编译选项优化技巧(2023最新版)

本文深入探讨了Synopsys VCS 2023版本中的高级编译选项优化技巧,帮助工程师提升仿真效率。通过并行编译、智能代码分析、精准覆盖率采样等策略,结合真实案例展示如何显著缩短仿真周期并优化资源使用,适用于数字芯片验证和大型SoC设计。

weixin_30338481的博客 113

保姆级教程:从WOS下载文献到Citespace出图,手把手搞定科研可视化(附避坑指南)

本文提供从WOS下载文献到Citespace出图的完整科研可视化指南,涵盖数据采集、清洗、环境配置和可视化优化全流程。特别分享WOS检索技巧、数据清洗方法和Citespace参数设置,帮助科研新手高效生成专业图谱,避开常见技术陷阱。

weixin_29311017的博客 171

c++中new的三种用法详细解析

一. 简介 new有三种使用方式:plain new,nothrow new和placement new。 (1)plain new顾名思义就是普通的new,就是我们惯常使用的new。在C++中是这样定义的:     void* operator new(std::size_t) throw(std::bad_alloc);     void operator delete(void

skylark的总结 2728

银河麒麟V10离线升级OpenSSH实战:从编译到回滚全流程

OpenSSH作为Linux系统远程登录的核心组件,其版本升级直接关系到系统安全与等保合规。在信创环境下,银河麒麟V10自带的OpenSSH版本往往无法满足漏洞扫描与安全加固要求,而离线编译升级涉及依赖处理、编译参数、服务替换与回滚方案等多个技术环节。本文围绕银河麒麟V10(x86_64)平台,详细讲解OpenSSH离线升级的完整实操流程,包括环境摸底、依赖包安装、源码编译、配置文件兼容性处理、服务重启验证以及常见问题排查,并分享批量升级与安全加固的工程经验,帮助运维人员在不断网、不重装的前提下一次成功完成

weixin_30582943的博客 383

operator new与placement new

placement new就是在用户指定的内存位置上构建新的对象,这个构建过程不需要额外分配内存,只需要调用对象的构造函数即可。举例来说: class foo{}; foo* pfoo = new foo; pfoo指向的对象的地址是不能决定的,new做了这些工作。第一步分配内存,第二步调用类的构造函数。 分配内存这一操作是由operator new(size_t)来完成的,如果类重载了operator new,将调用foo::operator new(size_t ),否则调用全局::operator

qq_44272681的博客 1160

【面试题】MySQL索引相关的面试题(红黑树,hash,B树,B+树)

自己整理了几个面试题分享给大家 问题1:红黑树为什么那样设计? 首先聊一下二叉搜索树,主要特点是左节点比根节点小,右节点比根节点大,并且左右子树都是二叉搜索树。缺点是在极端情况下,比如插入都是有序的,就会出现退化的情况有序序列树退化成链表。 二叉搜索树 退化成链表的二叉搜索树 此时,要想让树的节点平均分布就需要平衡树了,红黑树就是平衡树的一种(平衡二叉搜索树)。然后,一棵树的查询性能取决...

Mr_黑_ 的博客 4042

先进封装类别分析与典型案例

当制程微缩逼近物理极限、单颗大芯片(reticle limit)面积受限于光罩尺寸,且逻辑、存储、射频、传感等功能无法用同一套工艺最经济地制造时,性能增益的来源从 "晶体管密度" 转向 "互连密度"。先进封装的本质,是在芯片外部用更短、更密、更宽的路径把多个裸 die(die)互连起来,换取更高带宽、更低延迟、更小体积和异构集成能力。行业通常按划分为 2D、2.5D、3D、扇出、SiP 五大谱系,Chiplet/UCIe 则是贯穿其上的设计方法论,玻璃基板、共封装光学(CPO)是正在成型的新分支。

0 30

C++中的new、operator new与placement new

C++中的new、operator new与placement new

小x的博客 1352

【OpenClaw从入门到精通】第13篇:OpenClaw低代码编排实战:非技术人员也能玩转AI自动化流程(2026新版实测)

本文聚焦OpenClaw 2026版核心升级的低代码编排能力,针对非技术人员的实操需求,从底层逻辑、双环境部署、三类实战案例、避坑指南四个维度展开。详解阿里云集群版(企业级)与汉化本地版(个人调试)的部署步骤,通过基础数据统计、公众号内容生产线、企业级任务调度三个递进式案例,演示可视化拖拽搭建自动化流程的完整过程。全程零代码/低代码操作,配套详细参数配置、执行结果模拟及问题排查方案,帮助销售、运营、自媒体等非技术人员快速掌握自动化工具,将重复工作交给AI,提升核心工作效率。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 615

C++ 中 new 操作符内幕:new operator、operator new、placement new

一、new 操作符(new operator) 人们有时好像喜欢故意使C++语言的术语难以理解。比如说new操作符(new operator)和operator new的区别。  当你写这样的代码: string *ps = new string("Memory Management");你使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总

buxizhizhou530的专栏 1476

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

C++ new 之 placement new、operator new、new operator

C++ new 之 placement new、operator new、new operator

u014023993的专栏 636

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: 函数调用栈和栈帧
下一篇: Placement new、operator new、new operator 完全释疑
xufeichen
博客等级 码龄19年 1粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值