C小坑一枚new和deletee未配

北京中科白癜风专治白癜风 https://yyk.39.net/bj/zhuanke/89ac7.html

蝎子

在之前的文章中,我提到过,如果new和delete这两条指令没有准确地配对使用,则可能会造成一些麻烦,那么,今天就来详细说道说道。

网上有这样一篇文章《C++Gotchas:AvoidingCommonProblemsinCodingandDesign》,里面有一个掌节《FailuretoDistinguishScalarandArrayAllocation》我建议你在阅读下面的文章之前先看看,因为我会引用里面提到的一些内容。

微软C++编译器是这样来处理内存的矢量分配的。请注意,这里讨论的都是内部的实现细节,所以将来可能会发生改变,但是理解里面的工作原理,有助于理解为什么错误的使用new和delete是一件糟糕的事情。

实现细节

重要的是,当你使用标量化的”deletep”时,你实际上是在告诉编译器:指针p是指向的是一个单一的对象。编译器仅仅会调用析构器一次,对于该对象而言,它即将进行析构了。

当你调用矢量化的”delete[]p”时,你是在跟编译器说:指针p指向了一组对象,但是我不能告诉你对象的数量。在这种情况下,编译器需要生成额外的代码来记录它到底需要析构多少个对象。这个所谓的额外信息是存放在调用”new[]”进行内存分配时创建的一个安全的地方。

我们来看看下面这个例子:

编译器对allocate_stuff函数生成汇编代码如下:

将上面的汇编代码转换为伪C++代码,如下所示:

换句话说,MyClass对象数组的内存布局,如下所示:

new[]操作符返回的指针不是已分配内存的起始位置,而是一个指向MyClass[0]的指针。分配对象的数量信息实际上保存在数组前面的隐藏空间。

让我们看看下面的代码:voidfree_stuff(MyClass*p){delete[]p;}

它生成的汇编代码如下:

然后,我们再将汇编转为伪C++代码,如下所示:voidfree_stuff(MyClass*p){if(p)p-vectordeletingdestructor(3);}

对于数组对象的析构流程,类似下图:

数组的析构操作会用到一些标志位,如果2被设置,则数组会被析构,否则,只有单个对象被析构。如果1被设置,则内存空间也会被释放。

在我们的例子中,标志位被设置为,因此我们将执行一个数组析构并释放内存空间。请注意,本来用于存储对象数量的隐藏区域会被释放,并且数组析构器会在内存空间被释放之前执行非常多次的析构操作。

所以,现在你应该也有点感觉了:使用new分配内存空间,并使用delete[]来释放将会给你带来麻烦。

课后练习题

如果对象的析构函数MyClass::~MyClass()从类定义中被移除,可以有哪些方式来对代码进行优化?

总结

记住一点就够:用new必须用delete,用new[]必须用delete[]。也算是C++的一个小坑吧。

最后

RaymondChen的《TheOldNewThing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。本文来自:《Mismatchingscalarandvectornewanddelete》




转载请注明:http://www.aierlanlan.com/rzdk/1258.html

  • 上一篇文章:
  •   
  • 下一篇文章: 没有了