如何删除“知道”操作数数组的大小?
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 []不必做任何事情,因此不需要存储任何东西!