关系经济人类预测化学自然
中准网
自然科学
知识物理
化学生物
地理解释
预测理解
本质社会
人类现象
行为研究
经济政治
心理结构
关系指导
人文遗产

C中的newoperatornew与placementnew

4月28日 莫思归投稿
  当我们使用了new关键字去创建一个对象时,你知道背后做了哪些事情吗?AanewA;
  实际上这样简单的一行语句,背后做了以下三件事情:分配内存,如果类A重载了operatornew,那么将调用A::operatornew(sizet)来完成,如果没有重载,就调用::operatornew(sizet),即全局new操作符来完成。调用构造函数生成类对象;返回相应指针。
  下面我们通过一个例子来验证这个过程:includeiostreamincludestringincludemalloc。studentclassclassStu{public:Stu(stringname,intage){coutcallS};public:voidprint()const{coutnamenamestd::coutageagestd::};voidoperatornew(sizetsize){std::coutcalloperatornewstd::returnmalloc(size);}private:};intmain(){Stustu1newStu(a,10);}
  在上述代码中,我们重载了Stu类的operatornew操作符,用来验证上述对于new关键字的描述。
  上述代码的执行结果如下所示:calloperatornewcallStuclassconstructor
  可以看到重载的operatornew被调用,类Stu的构造函数也被调用,验证了上述的描述。
  要注意到的是new是一个关键字,和sizeof一样,我们不能修改其具体功能。operatornew
  从new的调用过程中,我们知道会调用operatornew操作符
  那么operatornew又是什么呢?
  C支持运算符的重载,支持对一些运算符自定义其行为:
  operatornew
  operatornew是一个操作符,和操作符一样,作用是分配空间。我们可以重写它们,修改分配空间的方式。
  operatornew返回值必须是void。第一个参数必须是sizetvoidoperatornew(std::sizetsize)throw(std::badalloc);voidoperatornew(std::sizetsize,conststd::nothrowtnothrowconstant)throw();
  在下面的例子中,我们使用重载了三个operatornew方法,并分别调用。includeiostreamincludestringincludemalloc。studentclassclassStu{public:Stu(stringname,intage){coutcallS};Stu(){}public:voidprint()const{coutnamenamestd::coutageagestd::};voidoperatornew(sizetsize){std::coutcalloperatornewstd::returnmalloc(size);}voidoperatornew(sizetsize,intnum){std::coutcalloperatornewwithintstd::returnmalloc(size);}voidoperatornew(sizetsize,charc){std::coutcalloperatornewwithcharstd::returnmalloc(size);}private:};intmain(){Stustu1newStu(a,10);Stustu2new(1)Stu(a,10);Stustu3new(c)Stu(a,10);deletestu1;deletestu2;deletestu3;}
  执行结果如下:calloperatornewcallStuclassconstructorcalloperatornewwithintcallStuclassconstructorcalloperatornewwithcharcallStuclassconstructorcalldestructorcalldestructorcalldestructor
  可以看到重载的三个operatornew被成功调用。placementnew
  placementnew是operatornew的一种重载形式,其作用是可以在指定的内存地址创建对象。
  placementnew返回值必须是void。第一个参数必须是sizet,第二个参数是voidvoidoperatornew(std::sizetsize,voidptr)throw();
  下面的是一个关于placementnew的调用例子:includeiostreamincludestringincludemalloc。studentclassclassStu{public:Stu(stringname,intage){};Stu(){}public:voidprint()const{coutnamenamestd::coutageagestd::};voidoperatornew(sizetsize,voidp){std::coutplacementnewstd::};private:};intmain(){charbuff(char)malloc(sizeof(Stu));Stustunew(buff)Stu(stu1,10);stuprint();stuStu();free(buff);}
  执行结果如下:placementnewnamestu1age10calldestructor
  由于placementnew可以在一个指定的位置创建对象,因此在STL中有很广泛的运用,例子vector容器初始化的时候,会使用allocator申请一定的内存,当使用pushback放入对象时,就可以使用placementnew在申请的位置创建对象。
  这里以MyTinySTL中创建对象的函数为例,construct。hopeninnewwindow,可以看出construct函数就是使用了全局的placementnew方法在指定地址创建对象。templateclassTy,class。。。Argsvoidconstruct(Typtr,Args。。。args){::new((void)ptr)Ty(mystl::forward(args)。。。);}
  需要注意的是,placementnew只是在指定的内存地址上构建对象,在对象使用完毕之后,需要手动调用析构函数做资源的析构。charbuff(char)malloc(4096);Stustunew(buff)Stu(stu1,10);stuprint();stuStu();free(buff);
  为什么需要这样呢?
  我们知道,使用delete关键字去释放一个对象时,首先会调用析构函数,然后再调用operatordelete释放内存。
  但是由于内存的申请并不是通过new对象而申请的,而是通过malloc申请到的一块内存空间,placementnew只有借用了该内存空间去构建了对象,因此是不能使用delete关键字去直接释放该对象的。由于不能直接调用deletestu,这就会导致对象的析构函数不会被自动调用,因此我们需要手动调用对象的析构函数做对象的析构stuStu(),最后使用与malloc配套的free释放申请到的内存空间。
  此外,我们讨论另外一个问题,placementnew可以在栈上构建对象吗?
  答案是肯定的。includeiostreamincludestringincludemalloc。studentclassclassStu{public:Stu(stringname,intage){};Stu(){}public:voidprint()const{coutnamenamestd::coutageagestd::};voidoperatornew(sizetsize,voidp){std::coutplacementnewstd::};private:};intmain(){charbuff〔4096〕;Stustunew(buff)Stu(stu1,10);stuprint();stuStu();}
  与在堆上调用placementnew一样,同样需要手动调用析构函数做资源的释放。但是由于内存是在栈上的,因此不需要手动释放。结论
  对于new,operatornew和placementnew三者的区别,我们总结如下:
  new:
  new是一个关键字,不能被重载。
  new操作符的执行过程如下:调用operatornew分配内存;调用构造函数生成类对象;返回相应指针。
  operatornew:
  operatornew就像operator一样,是可以重载的。如果类中没有重载operatornew,那么调用的就是全局的::operatornew来完成堆的分配。同理,operatornew〔〕、operatordelete、operatordelete〔〕也是可以重载的。
  placementnew:
  placementnew和operatornew并没有本质区别。它们都是operatornew操作符的重载,只是参数不相同。
  placement并不分配内存,只是返回指向已经分配好的某段内存的一个指针。因此不能使用delete关键字删除它,需要手动调用对象的析构函数。
  如果你想在已经分配的内存中创建一个对象,使用new时行不通的。也就是说placementnew允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中voidp实际上就是指向一个已经分配好的内存缓冲区的的首地址。
投诉 评论 转载

秦晓雯和张云松休赛期一无所获!方硕可能被交易!解立彬未确定最近北京队也开始进行集训开始,但是球队核心之一方硕并没有随着北京进行训练,之前有消息说方硕是因为自己的伤病问题没有归队,但是近期有很多消息说,方硕没有归队并不是因为伤病,而是方……英超2遭升班马逼平努涅斯首秀传射救主萨拉赫破门北京时间8月6日晚19点30分,20222023赛季英超联赛首轮迎来了一场焦点战利物浦客场对阵升班马富勒姆。上半场,米特洛维奇头球破门,帮助主队领先红军;下半场,利物浦新援努涅……龙虎山下,泸溪河上赶筏人川观新闻记者尹钢4月13日,江西省鹰潭市龙虎山下,云遮雾绕的泸溪河上,一只只小小竹筏载着游人观赏两岸烟雨中的山水奇观。龙虎山最美的风景只有乘咱们的竹筏才能看到。当游……海外已加入车队干活,特斯拉Semi卡车正式交付百事可乐文:懂车帝原创宋爱菊〔懂车帝原创行业〕连特斯拉CEO埃隆马斯克也不得不承认,特斯拉Semi卡车是公司历史上延迟时间最长的产品之一。但它如今终于被交付给了首批客户百事可乐,……安徽造车狂人,第四次IPO敲钟市值2700亿来源:天天IPO(ID:pedailyIPO)作者:刘博杨继云李斌还是来了。投资界3月10日消息,今日,蔚来汽车正式登陆港交所,首日开盘报每股160港元,港股市值2……坚持不下去时,不妨看看这段话点上方听一禅第2133次和你说晚安文一禅主播一禅苏轼曾说:古之立大事者,不惟有超世之才,亦必有坚忍不拔之志。人生如海,潮起又潮落。一路上有春风得意马蹄疾……痧是什么?结节是什么?癌是什么?老中医告诉你实情分享来源:经络通全身痧是什么离经之血!结节是什么气血瘀滞物!癌是什么是长时间瘀滞物变异的结果!人体十四条经络是负责给我们全身供血的主要管道。我们的……自古英雄出少年,八十年代红极一时,为何主演一个都没火央视春晚前几年曾被网友调侃太重视流量,娱乐圈谁火谁流量大就请谁上春晚。其实央视春晚并不是近些年才开始重视流量,而是从一开始就很重视流量,第一届83年春晚四个主持人里有三位……鹿晗关晓彤聚餐后一起回家提醒关晓彤绝不要让鹿晗碰近日,鹿晗关晓彤被拍到聚餐后一起回家,鹿晗喝醉了被友人搀扶出来,关晓彤随后也和朋友出来,告别后上了鹿晗的车一起回家。有网友说:鹿晗关晓彤不得偷吃禁果,听见了没有!著……油价调整消息今天10月11日,调整后全国9295号汽油柴油限新一轮的油价调整计价周期将要开启,最终横跨国庆假期的调整最终结果以搁浅收尾,不过从上一次调整初期到最后时间都可以看出原油市场的波动较大,这也为即将开启的新的计价周期埋下伏笔,接……直通德班19日上午战况,薛飞速胜林高远,赵子豪遭遇两连败在直通德班比赛19日上午进行的比赛中,王楚钦、刘丁硕、林高远、薛飞、梁靖崑、赵子豪等国乒名将登场。在首场一号台的比赛中,王楚钦展现了极强的进攻能力,3:0战胜刘丁硕。本场……C中的newoperatornew与placementnew当我们使用了new关键字去创建一个对象时,你知道背后做了哪些事情吗?AanewA;实际上这样简单的一行语句,背后做了以下三件事情:分配内存,如果类A重载了operator……
韩德君郭少消失!CBA伤病报告让辽宁放心,广东2人报销他们或关键词挖掘工具长尾关键词挖掘精灵下载使用及评测报开放式厨房燃气热水器安装位置新手微商怎么找精准客源如何快速加到精准好友看完你宫寒吃什么食物好种食物暖宫效果好妻子造句用妻子造句大全CBA至今27年历届得分王里只有四位是本土球员,看看他们都是80亿美元换来一地鸡毛?外媒高通芯片已经失去了优势姓贺的女孩名字洋气的云南再现黑导游,白领至少消费8000元,肥了自己坑了云南鹿晗关晓彤年底即将分手?网传关晓彤不愿意结婚鹿晗苦等不到结果宇宙知识一
辛勤造句用辛勤造句大全把命运掌握在自己手中什么是房屋转租,哪些情形房屋不能转租三战全败!卡塔尔成最惨东道主,创世界杯尴尬纪录,小王子赚翻我的快乐初一作文热传聚热点网 开展成本精细化管理提高企业经济效益幼儿教师辞职报告15篇冠心病晕厥如何治疗我也要歇伏转应曲暮春【关注世界环境日】绿色和平全球总干事:中国在全球环境治理的角怎么做造句用怎么做造句大全

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找菏泽德阳山西湖州宝鸡上海茂名内江三亚信阳长春北海西安安徽黄石烟台沧州湛江肇庆鹤壁六安韶关成都钦州