范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

C深入理解预定义重载操作符new(placementoperatornew)

  对于动态内存管理,C语言的做法是使用库函数手动申请和释放动态内存空间,到了C++,新增了两个关键字(new、delete),另外,分别与[]结合,构成4上操作符(new、delete、new []、delete [])。为对象动态申请和使用动态内存的new、delete、不仅有相关的内存操作,还会分别调用构造函数和析构函数。Complex* pc = new Complex(1,2);
  相当于:Complex *pc;void* mem = operator new( sizeof(Complex) ); //分配內存pc = static_cast(mem); //轉型pc->Complex::Complex(1,2); //構造函數
  析构操作:delete pc;
  相当于:Complex::~Complex(pc); // 析構函數operator delete(pc); // 釋放內存
  new [] 需要有配对操作delete [],否则会出现动态内存泄漏:
  对于C++,大部分操作符都可以重载,其中就包括了上述4个操作符。
  A predefined overloaded instance of operator new is that of the placement operator new. It takes a second argument of type void*. The invocation looks as follows:
  运算符new的预定义重载实例是placement operator new的预定义重载实例。它接受类型为void*的第二个参数。调用如下所示:Point2w ptw = new ( arena ) Point2w;
  where arena addresses a location in memory in which to place the new Point2w object. The implementation of this predefined placement operator new is almost embarrassingly trivial. It simply returns the address of the pointer passed to it:
  其中arena在内存中寻址放置新Point2w对象的位置。这种预定义的placement operator new的实现几乎微不足道。它只返回传递给它的指针的地址:void* operator new( size_t, void* p ){    return p;};
  If all it does is return the address of its second argument, why use it at all? That is, why not simply write
  如果它所做的只是返回第二个参数的地址,那么为什么还要使用它呢?也就是说,为什么不直接写呢Point2w ptw = ( Point2w* ) arena;
  since in effect that"s what actually happens? Well, actually it"s only half of what happens, and it"s the second half that the programmer cannot explicitly reproduce. Consider these questions:
  实际上,这就是实际发生的事情?实际上,这只是发生的事情的一半,这是程序员无法显式重现的第二部分。考虑以下问题:
  1. What is the second half of the placement new operator expansion that makes it work (and that the explicit assignment of arena does not provide for)?
  placement new operator 扩展的后半部分是什么使其工作(arena的显式分配没有提供)?
  2. What is the actual type of the pointer represented by arena and what are the implications of that type?
  arena表示的指针的实际类型是什么?该类型的含义是什么?
  The second half of the placement new operator expansion is the automatic application of the Point2w constructor applied to the area addressed by arena:
  placement new operator扩展的后半部分是应用于arena所处理区域的Point2w构造函数的自动应用:// Pseudo C++ codePoint2w ptw = ( Point2w* ) arena;if ( ptw != 0 )    ptw->Point2w::Point2w();
  This is what makes the use of the placement operator new so powerful. The instance determines where the object is to be placed; the compilation system guarantees that the object"s constructor is applied to it.
  这就是为什么placement operator new的使用如此强大。实例确定对象放置的位置;编译系统保证对其应用对象的构造函数。
  There is one slight misbehavior, however. Do you see what it is? For example, consider this program fragment:
  然而,有一个轻微的不当行为。你看到它是什么了吗?例如,考虑以下程序片段:// let arena be globally definedvoid fooBar() {    Point2w *p2w = new ( arena ) Point2w;    // ... do it ...    // ... now manipulate a new object ...    p2w = new ( arena ) Point2w;}
  If the placement operator constructs the new object "on top of" an existing object and the existing object has an associated destructor, the destructor is not being invoked. One way to invoke the destructor is to apply operator delete to the pointer. But in this case, that"s the absolutely wrong thing to do:
  如果placement operator在现有对象的"顶部"构造新对象,并且现有对象具有关联的析构函数,则不会调用析构函数。调用析构函数的一种方法是将运算符delete应用于指针。但在这种情况下,这样做是绝对错误的:// not the right way to apply destructor heredelete p2w;  p2w = new ( arena ) Point2w;
  The delete operator applies the destructor—this is what we want. But it also frees the memory addressed by p2w—this is definitely not what we want, since the next statement attempts to reuse it. Rather, we need to explicitly invoke the destructor and preserve the storage for reuse:
  delete操作符应用析构函数这就是我们想要的。但它也释放了p2w寻址的内存,这肯定不是我们想要的,因为下一个语句试图重用它。相反,我们需要显式调用析构函数并保留存储以供重用:Standard C++ has rectified this with a placement operator delete that applies the destructor to the object but does not free the memory. A direct call of the destructor is no longer necessary.
  标准C++通过placement operator delete纠正了这一问题,该操作符将析构函数应用于对象,但不会释放内存。不再需要直接调用析构函数。// the correct way of applying destructorp2w->~Point2w;p2w = new ( arena ) Point2w;
  The only remaining problem is a design one: Does the first invocation of the placement operator in our example also construct the new object "on top of" an existing object, or is the arena addressed "raw"? That is, if we have
  剩下的唯一问题是设计问题:在我们的示例中,placement operator的第一次调用是否也会在现有对象的"顶部"构造新对象,或者arena是否被寻址为"原始"?也就是说,如果我们有Point2w *p2w = new ( arena ) Point2w;
  how can we know whether the area addressed by arena needs first to be destructed? There is no language-supported solution to this. A reasonable convention is to have the site applying new be responsible for also applying the destructor.
  我们怎么知道arena所涉及的区域是否需要首先被破坏?没有语言支持的解决方案。一个合理的惯例是让申请新的地址也负责申请析构函数。
  The second question concerns the actual type of the pointer represented by arena. The Standard says it must address either a class of the same type or raw storage sufficient to contain an object of that type. Note that a derived class is explicitly not supported. For a derived class or otherwise unrelated type, the behavior, while not illegal, is undefined.
  第二个问题涉及arena表示的指针的实际类型。该标准表示,它必须处理相同类型的类或足以包含该类型对象的原始存储。请注意,显式不支持派生类。对于派生类或其他不相关的类型,行为虽然不非法,但未定义。
  Raw storage might be allocated as follows:
  原始存储可以按以下方式分配:char *arena = new char[ sizeof( Point2w ) ];
  An object of the same type looks as you might expect:
  相同类型的对象看起来与您预期的相同:Point2w *arena = new Point2w;
  In both cases, the storage for the new Point2w exactly overlays the storage location of arena, and the behavior is well defined. In general, however, the placement new operator does not support polymorphism. The pointer being passed to new is likely to address memory preallocated to a specific size. If the derived class is larger than its base class, such as in the following:
  在这两种情况下,新Point2w的存储正好覆盖arena的存储位置,并且行为定义良好。然而,通常情况下,placement new operator不支持多态性。传递给new的指针可能会寻址预分配到特定大小的内存。如果派生类大于其基类,例如:Point2w p2w = new ( arena ) Point3w;
  application of the Point3w constructor is going to wreak havoc, as will most subsequent uses of p2w.
  Point3w构造函数的应用将带来巨大的破坏,p2w的大多数后续使用也将如此。
  One of the more "dark corner-ish" questions that arose when the new placement operator was introduced in Release 2.0 was the following example brought up by Jonathan Shopiro:
  在2.0版中引入new placement operator时,出现了一个更为"黑暗角落"的问题,乔纳森·肖皮罗(Jonathan Shopiro)提出了以下示例:struct Base { int j; virtual void f(); };struct Derived : Base { void f(); };void fooBar() {    Base b;    b.f(); // Base::f() invoked    b.~Base();    new ( &b ) Derived; // 1    b.f(); // which f() invoked?}
  Since the two classes are the same size, the placement of the derived object within the area allocated for the base class is safe. Supporting it, however, would probably require giving up the general optimization of invoking statically all virtual functions calls through objects, such as b.f().
  由于这两个类的大小相同,因此将派生对象放置在为基类分配的区域内是安全的。然而,支持它可能需要放弃通过对象(例如b.f())静态调用所有虚拟函数调用的一般优化。
  Consequently, this use of the placement new operator is also unsupported under the Standard. The behavior of the program is undefined: We cannot say with certainty which instance of f() is invoked. (Most implementations, if they were to compile this, would probably invoke Base::f(), while most users would probably expect the invocation of Derived::f().)
  因此,该标准也不支持使用placement new运算符。程序的行为尚未定义:我们无法确定调用了f()的哪个实例。(大多数实现如果要编译它,可能会调用Base::f(),而大多数用户可能希望调用Derived::f()。)
  ref
  Stanley B. Lippman 《Inside the C++ Object Model》
  《cpp annotations》cplusplus09.html#l179
  -End-

曝快船独行侠有意交易得到欧文,篮网未否定交易可能性近日,著名NBA记者扎克洛维在节目中透露,快船和独行侠有意交易得到欧文,而篮网现在没有放弃欧文,他们现在闭口不谈关于交易欧文的事情。这意味着篮网未否定交易欧文的可能性!而篮网跟队记亚足联官方东道主印度队退出女足亚洲杯中国女足成绩不受影响北京时间1月24日下午,亚足联官方宣布,2022女足亚洲杯东道主印度队因队内疫情严重,退出女足亚洲杯。亚足联官方公告继2022年亚足联印度女足亚洲杯A组第2轮中国台北队与印度队的比东体洛国富对个人行为表达歉意,表示踢好比赛最重要直播吧1月24日讯据东方体育日报报道,洛国富在和国足方面沟通协调后就个人行为给球队带来的影响表达了歉意。东体透露,一位队内人士在谈到早些时间曝出的洛国富抱怨不受尊重一事时表示这个事马龙晒乒乓球家庭大合照!刘国梁穿西装站C位,老将扎堆站角落近日,知名乒乓球运动员马龙在自己的社交平台上晒出了乒乓球大家庭的合照,老将新将扎堆站在队伍中,刘国梁穿着一身西装占C位,并且配文乒乓大家庭,收官再战,提前祝大家虎年快乐,虎虎生威。王楚钦或成马龙接班人,王曼昱有新一姐实力,许昕刘诗雯宝刀不老WTT澳门冠军赛落下帷幕,冠军归属已定,新的一年,新的周期,国乒众将士们均展现了良好的竞技状态与精神风貌,老将们的状态保持的相当出色,同时年轻新人已经逐渐成长起来,2024年的巴黎70亿最强格斗男诞生!铁血纳干诺苦战5局,点数击败盖恩成功卫冕它被称为70亿最强男铁血纳干诺,是现役UFC重量级冠军,他用出色的打法征服UFC重量级拳坛,他也是世界拳王泰森的得意大弟子。2022年1月23日,UFC270将迎来重量级世纪大战,湖人憾负!詹皇33分,威少2499,赛后威少率先退场,谁留意老詹6952,半场结束热火暂时领先湖人17分,我们先来看一下双方球员的半场数据,热火一方邓罗16分2板,巴特勒6分7板10助,阿德巴约8分6板3助,塔克3分2助,文森特9分5助,斯特鲁冠军赛发挥出色的队员排名出炉,陈梦仅排第五,刘诗雯强势排第二冠军赛发挥出色的队员排名出炉,陈梦第五,刘诗雯第二,第一太强众所周知,WTT澳门冠军赛已于昨天落下帷幕,而在本场赛事当中有非常多的女乒队员发挥的非常出色。而有些感兴趣的球迷也选出了活久见!女足亚洲杯东道主退赛,其他队呢?北京时间23日,亚足联官方确认,由于队内多人确诊新冠,印度女足已不能排出满足大赛最低要求的13人阵容。该队放弃比赛的同时,也触发了退赛条款。这样一来,中国女足就提前获得了小组头名。辽宁,为什么超越不了广东?辽宁,永远都超越不了广东,不是你没有实力,而是你永远不知道对手有多拼命!为什么广东11个冠军,辽宁只有1个?为什么广东能3连冠,建立又一个王朝,辽宁至今也打造不了一个王朝?为什么全回归理性上港需要认真反思,泰山队不原谅徐新,与他的实力无关(全文约4412字,阅读时长约12分钟,深度剖析徐新转会的相关问题。)徐新转会事件,直到今天为止,热度逐渐降了下来,大家也慢慢地接受了这个现实。我们再去回头看看这件事的始末,很多球
传奇世界法师技能详细介绍以及如何对应的选择学习哈喽,大家好,我是阿曼,今天我们详细介绍下法师的技能。1,法师一共有26个技能,介绍如下小火球基本攻击魔法,杀伤力会随着训练等级的提高而提升。抗拒光环了保护自己几乎毫无防御的身体,新年伊始回顾下你在英雄联盟游戏账户上花了多少钱新的一年已经来了,作为游戏玩家,你是否很想知道你在英雄联盟(LOL)游戏账户上到目前为止共花了多少钱?如果你是个大R玩家,自创建账户以来已经花费了超过1万人民币,看到你在一个所谓的街霸对决追溯本心突破极限,火豹阿顿技能首曝12月31日,街霸对决将迎来一位全新格斗家,实力强悍的火豹阿顿即将降临街霸世界,展现泰拳格斗技巧的独特魅力。届时游戏将开启限时招募活动,大家参与招募即有机会获得火豹阿顿。不仅如此,魔兽世界盘点因GM误操作而落入玩家之手的神器,太离谱了各位小伙伴你们好,我是细细说,欢迎收看今天的节目。在魔兽世界漫长的发展过程当中,曾经数次出现过暴雪官方工作人员(GM)误操作而导致一些神器落入玩家之手的情况。我确信有些大家早已听说梦幻西游投入2万元的129级五开,每天在线5小时,月收入3000?在梦幻西游这款游戏里面五开刷任务赚钱是公认最稳定的玩法,只要你不玩几率,同时舍得投入成本与时间,那么赚钱是肯定的。当然,高投入有高回报,回报的大小是根据你个人的投入的。但目前五开刷历史上臭名昭著的海盗黑胡子刺客信条4黑旗黑胡子的原型游戏形象在刺客信条4黑旗中,黑胡子艾德萨奇是一个较为关键的角色。1715年9月,拿索海盗欲加强拿索海湾的防御,爱德华肯维(男主角)与黑胡子艾德萨奇跟踪圣殿大师的方舟号到大伊纳瓜(G每日游戏报外媒评选2021PC版优化最令人失望的游戏一外媒评选2021PC版优化最令人失望的游戏2021最令人失望游戏2021年对于游戏来说是非常奇怪的一年,在这一年里我们看到了很多在发布初期出现了很大问题的PC游戏版本。而近日,外教育基地假期游元旦游路线推荐之觉醒年代党的早期革命活动历史之旅编者按每逢节假日,爱国主义教育基地都会迎来红色旅游热潮。观众们在各具特色的展览和活动中重温红色历史,感悟初心使命,汲取奋斗力量。游京华大地,践爱国之行。京华丹心结合全年节假日的重要文艺的意大利人中世纪风格的街道,墙面斑驳的老教堂,三三两两坐在教堂台阶前聊天的闲人,这是意大利艳阳下懒懒散散的样子。空气中飘着若有似无的咖啡香,耳边传来轻快的民间小调,橱窗里摆放着刚刚烘焙好的点千载人杰江山万里丨2022年上半年国内最值得看的六场大展2022年的第一个月,元旦假期与春节假期刚好排在一头一尾。喜欢看展览逛博物馆的小伙伴们,大概也在关心如何利用这难得的假期出趟门,看上一场精彩的展览,给新的一年留下值得回忆的开场秀。头发油腻怎么办?这几款控油洗发水你一定要知道关注彬彬OK仔带你了解更多护肤知识!以前,我看到别人在网上问头发油,怎么办?之类的话题的时候,我都会参考自己的情况,叫大家不要太在意洗发水的类型,要注意规律作息,只要不熬夜,头发就