【发布时间】:2013-12-25 05:29:26
【问题描述】:
在 C 中制作自动扩展数组(如 C++ 的 std::vector)时,通常(或至少常见的建议)每次填充数组时将数组的大小加倍以限制对 @ 的调用量987654321@为了尽量避免复制整个数组。
例如。我们首先为 8 个元素分配空间,插入 8 个元素,然后为 16 个元素分配空间,再插入 8 个元素,再分配 32 个元素,等等。
但realloc如果可以扩展现有的内存分配,则不必实际复制数据。例如,以下代码在我的系统上只执行了 1 次复制(初始 NULL 分配,因此它不是真正的复制),即使它调用了 realloc 10000 次:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int i;
int copies = 0;
void *data = NULL;
void *ndata;
for (i = 0; i < 10000; i++)
{
ndata = realloc(data, i * sizeof(int));
if (data != ndata)
copies++;
data = ndata;
}
printf("%d\n", copies);
}
我意识到这个例子是非常临床的 - 一个真实世界的应用程序可能会有更多的内存碎片并且会做更多的副本,但即使我在 realloc 循环之前进行了一堆随机分配,它只会稍微更糟用 2-4 份代替。
那么,“倍增法”真的有必要吗?每次将元素添加到动态数组时,只调用realloc 不是更好吗?
【问题讨论】:
-
您的 O(N) 算法从根本上比双倍分配提供的 O(logN) 算法差。
-
你的算法是一个稳定增长的内存需求,没有干预释放,所以它当然不需要复制。尝试在循环中添加随机大小和随机穿插的
malloc和free调用。 -
@Mike,你总是必须在这里做“最坏情况”的考虑:考虑每一步都需要复制的情况。在这种情况下,您使用这种方法肯定会生活得更好。不用每次都加倍,
* 1.5也可以,这样会导致增长速度变慢,但每一步都比+ 1好。即使+ 1000在需要时使用它也会比+ 1更好,但扩展性不是很好。但是,如果您有一定的最大限制,那也可以。
标签: c