如何删除“知道”操作数数组的大小?

Foo* set = new Foo[100]; // ... delete [] set; 

你不通过数组的边界来delete[] 。 但是,这些信息存储在哪里? 它是标准化的吗?

当你在堆上分配内存时,你的分配器会跟踪你分配了多less内存。 这通常存储在您分配的内存之前的“head”段中。 这样当释放内存的时候,解除分配器确切地知道要释放多less内存。

编译器的一种方法是分配更多的内存,并在head元素中存储一些元素。

示例如何完成:

这里

 int* i = new int[4]; 

编译器将分配sizeof(int)*5个字节。

 int *temp = malloc(sizeof(int)*5) 

将在第一个sizeof(int)字节中存储“4”

 *temp = 4; 

并设置i

 i = temp + 1; 

所以i会指出一个4个元素的数组,而不是5个。

和删除

 delete[] i; 

将按以下方式处理:

 int *temp = i - 1; int numbers_of_element = *temp; // = 4 ... call destructor for numbers_of_element elements ... that are stored in temp + 1, temp + 2, ... temp + 4 if needed free (temp) 

信息不规范。 然而,在我所处理的这个平台上,这个信息存储在第一个元素之前的内存中。 因此,理论上可以访问它并检查它,但是这不值得。

这也就是为什么当你使用new []分配内存的时候你必须使用delete [],因为delete的数组版本知道它需要注意释放适量的内存,并调用适当数量的析构函数为对象。

基本上它被安排在记忆中:

[信息] [你要求的…]

其中info是编译器用于存储分配内存量的结构,而不是。

虽然这是依赖于实现的。

这不是规范中的东西 – 它依赖于实现。

因为要删除的数组应该是用“new”操作符创build的。 “新”操作应该把这些信息放在堆上。 否则,如何额外使用新的知道堆的结束?

它在C ++标准中定义为编译器特定的。 这意味着编译器魔术。 至less可以在一个主要平台上打破非平凡的alignment限制。

你可以考虑通过实现delete[]只为new[]返回的指针定义可能的实现,它可能不是operator new[]返回的指针。 野外的一个实现是将数组的数量存储在operator new[]返回的第一个int中,并且new[]返回一个指针偏移量。 (这就是为什么非平凡的路线可以破坏new[] 。)

请记住, operator new[]/operator delete[] != new[]/delete[]

另外,这与C知道malloc分配的malloc大小是正交的。

它不是标准化的。 在微软的运行时,新的操作符使用malloc(),删除操作符使用free()。 所以,在这个设置你的问题是相当于以下内容:free()如何知道块的大小?

有一些簿记在幕后进行,即在C运行时。

这是一个比你想象的更有趣的问题。 这个答复是关于一个可能的实现。

首先,在某个级别上,系统必须知道如何“释放”内存块,底层的malloc / free(通常称为new / delete / new [] / delete [])通常并不总是记得有多less内存你要求,它可以得到四舍五入(例如,一旦你高于4K,它往往四舍五入到下一个4K大小的块)。

因此,即使可以获得内存块的大小,也不会告诉我们新的[] ed内存中有多less个值,因为它可以更小。 因此,我们必须存储一个额外的整数,告诉我们有多less个值。

除此之外,如果构造的types没有析构函数,那么除了释放内存块之外,delete []不必做任何事情,因此不需要存储任何东西!