C ++中的删除如何知道要删除多少内存位置

时间:2010-02-24 17:01:35

标签: c++ memory-management

删除操作符如何工作?它比free()更好吗?此外,如果您执行ptr=new char[10],然后使用delete ptr删除,指针如何知道要删除的位置数。

7 个答案:

答案 0 :(得分:16)

只有delete运算符,free仅作为函数存在。在C ++下,我们鼓励您使用new / delete而不是malloc() / free()


删除操作符中有一个内部“魔术”。使用new[]创建数组时,数组的大小存储在内存块的元数据中。 delete[]使用该信息。

所有这些当然都是编译器,操作系统,优化器和实现依赖。

答案 1 :(得分:5)

如果您执行非数组类型:

T t = new T;
// ...
delete t;

它会知道要删除多少,因为它知道T有多大。如果你做一个数组:

T t* = new T[10];
// ...
delete [] t;

它会在分配时放下一些额外的信息,告诉它要删除多少。注意,我们使用delete [] t和额外的[]来告诉它它是一个数组。如果你不这样做,它会认为它只是一个T并且只释放那么多记忆。

如果您使用delete,则始终使用new;如果您使用free,则始终使用mallocnew首先分配内存,然后构造对象。类似地,delete调用析构函数然后释放内存。 malloc\free只处理内存分配和释放。

答案 2 :(得分:3)

  1. 在C ++中,使用new调用构造函数,但在使用malloc时则调用。类似地,使用delete时会调用析构函数,但在使用free时不会调用析构函数。

  2. 如果您使用MyClass * x = new MyClass [25]创建了一个新数组,那么您需要调用delete [] x,以便系统知道它正在删除(和破坏)一组对象而不是单个对象。

答案 3 :(得分:3)

实现计算出要销毁的元素数量(当使用delete []时)。例如:

  • new char [10]可以分配一些额外的字节,将元素的数量放在开头,然后将指针返回到第一个元素。然后,delete []可以查看存储计数的指针
  • 存储等效的std :: map< void *,size_t>,而新的T [n]会创建一个带有返回指针的键,以及一个带有count的值。 delete []将在此地图中查找指针
  • 完全不同的东西。这对你来说并不重要,只是它完成了(正如其他答案所指出的那样,使用delete []和new [] !!)

答案 4 :(得分:3)

这不是一个好或坏的问题。两者都是具有相同目标的操作,分配和释放内存,但通常在C与C ++的不同上下文中使用。此外,两组操作之间存在一些重要差异:

  • new / delete是C ++关键字,在C语言中不可用
  • new / delete是类型安全的,而malloc() / free()则不是。这意味着malloc()free()返回的指针是void指针,需要转换为正确的类型。
  • new / delete使用new[]delete[]语法使用编译器提供的元数据malloc() / {隐式支持数组分配和删除{1}}不支持此语法
  • free() / new应用于类类型delete将分别调用TT / malloc()的构造函数和析构函数不要调用free()
  • 的构造函数和析构函数 如果内存耗尽,
  • T将返回malloc()NULL将引发异常

请注意,为防止内存损坏,应使用new释放使用new分配的内存。对于使用delete分配的内存也是如此,应使用malloc()释放内存。

答案 5 :(得分:3)

具体回答你的问题,删除操作符调用析构函数,其中free是不会;因此你不想将malloc / free与new / delete混合使用。

当编译器的库从堆中抓取内存时,它抓取的内容比你要求的多一点,其中包括空间保存,一些元数据,以及必要时填充。

假设您使用malloc 128字节,或者新建一个包含8个16字节大小的对象的数组。编译器实际上可能会抓取256个字节,在开始时包含一个小堆管理块,记录它给你128但是抓住了256,然后在它的标题之后的某个地方返回一个偏移到256块。您可以保证从该指针可以使用128个字节,但如果超出该字节,则可能会遇到麻烦。

引擎盖下的free和delete操作符将获取你所处理的指针,备份已知的偏移量,读取它的标题块,并知道将256个字节释放回堆中。

答案 6 :(得分:2)

如果使用运算符的new []形式分配内存,请添加@ Vlad的答案,如:

char *c = new char[10];

然后你必须使用相应的删除表格:

delete[] c;

您必须明确告诉编译器在重新分配期间使用元数据。

[编辑]

为什么你不能使用char c []

因为编译器需要知道在编译时需要为变量c留出的大小。但是,使用new []表单会告诉它将分配推迟到运行时。因此,编译错误。