作者:mobiledu2402851203 | 2023-09-04 10:12
在堆上分配内存时,分配器将跟踪已分配的内存量.这通常存储在您分配的内存之前的"head"段中.这样,当释放内存时,解除分配器确切地知道要释放多少内存.
1> QuantumPete..:
在堆上分配内存时,分配器将跟踪已分配的内存量.这通常存储在您分配的内存之前的"head"段中.这样,当释放内存时,解除分配器确切地知道要释放多少内存.
绝对没有理由不为程序员提供这些信息.我可以传递一个指向函数的指针并释放它,但是为了在同一个函数中自己获取大小,我必须传递一个额外的参数.这有任何意义吗?
对不起,但这个答案错过了重点.QuantumPete所描述的基本上是"如何`自由`知道要释放多少内存".是的,内存块大小由"malloc"存储在"某处"(通常在块本身中),这就是`free`知道的.但是,`new []`/`delete []`是一个不同的故事.后者基本上工作在`malloc` /`free`之上.`new []`还存储它在内存块中创建的元素数量(独立于`malloc`),以便后来的`delete []`可以检索并使用该数字来调用适当数量的析构函数.
即物理上有两个计数器存储在块中:块大小(通过`malloc`)和元素计数(通过`new []`).注意,前者不能用于计算后者,因为在一般情况下,存储块的大小可能大于所请求大小的阵列所需的大小.另请注意,只有具有非平凡析构函数的类型才需要数组元素计数器.对于具有普通析构函数的类型,计数器不是由`new []`存储的,当然,不是由`delete []`检索的.
@Mark,它有一点*小*的意义,因为理论上它确实释放了分配器总是存储*allocated*块的大小(可能与*requested*块的大小不同).某些分配器设计可能需要这些信息用于它们自己的目的,或者可能不够复杂,无法使用类型信息来跟踪非阵列堆分配的大小等.强制分配器存储所请求的大小(这样你就不会需要自己传递数组大小)可能是一个小的障碍,但它可能会对可想象的分配器设计产生性能影响.
请注意,这仅适用于C++中的数组分配.所有其他分配都依赖于类型的大小.有些库会存储所有分配大小,通常只在调试模式下.
马克的观点虽然如此.由于必须存储此信息,因此我们也没有理由不能访问它.如果它进行了全局分配,那么vector可以使用它来获得优势,但实际上,vector必须做无意义的额外分配和复制.如果它没有进行过度分配,那么我们就可以获得动态数组的数组大小.其中一个或两个都是有用的信息.
@ sasha.sochka:*编译器*不知道.`delete A`简单地调用`A`析构函数(如果它是虚拟的,多态性调用`B`析构函数),然后将'A`指向的内存块传递给*内存管理器*以便释放.*内存管理器*知道它分配了多少内存来满足`new B()`调用.
拒绝投票是因为,正如AnT指出的那样,它完全错过了要点,并且没有回答问题。确实应该删除(嘿),或修正它以给出正确的答案(如AnT的第二条评论中所述)。
2> Avt..:
编译器的一种方法是分配更多的内存并在头元素中存储元素的数量.
示例如何完成:
这里
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)
3> Daemin..:
信息不规范.但是,在我处理过的平台中,这些信息存储在第一个元素之前的内存中.因此,理论上你可以访问并检查它,但它不值得.
这就是为什么你在使用new []分配内存时必须使用delete [],因为delete的数组版本知道它需要查找(以及在哪里)释放适当数量的内存 - 并调用适当数量的析构函数对象.
4> Francisco So..:
基本上它在内存中排列为:
[info] [mem你问...]
其中info是编译器用于存储分配的内存量的结构,而不是.
这是依赖于实现的.