我已经在网上搜索了此内容,并询问了我的助教,但我没有得到非常可靠的答案。我正在测试用于插入和搜索数据的不同数据结构的性能。我正在测试的数据结构之一是哈希表。
我知道动态分配内存是有好处的,如果您不知道数组的结束大小,并且出于多种原因想要实现double数组。但是说我们知道数据量。在这种情况下,40,000个整数值。我是否需要在堆上动态分配数组,还是可以使用相同的功能并通过静态实例化堆栈来使用?我会做同样的事情,创建头文件,实现文件和main(),但不动态分配内存。
好问题。您可以在没有动态内存分配的系统上实现malloc,只需将一个大的空表放在malloc.c内,然后处理掉其中的一部分,直到用完为止。 Free会将块插入其中,因此您可能永远不会用完。
一种相关的内存分配方式是通过frame分配器(有时是池分配器);之所以命名,是因为它可以访问N M个大小的对象,而不是真正的动态分配器(每个对象的大小都不同)。帧分配器很棒,因为它们既快速又简单-一种罕见的组合。
因此,您当然可以在系统上工作而无需动态分配,但是您可能需要问自己为什么?您可以使用未指定的分配器来编写它,可以使用非常简单的框架分配器来实现,然后根据需要对其进行扩展。
这实际上取决于您所说的“动态分配”。
典型的哈希表包含一个存储桶数组(或指向存储桶的指针数组)。每个存储桶都存储散列到同一散列的事物的集合。因此,给定一个要存储在哈希表中的40000 int集合,您需要为每个存储桶集合本身提供某种形式的动态分配。
如果使用动态分配,您的意思是“对malloc的调用”,那么您可以使用“ placement new”或您自己的内存管理的其他形式来管理哈希表本身,存储桶集合,每个单独的存储桶集合的内存。您将计算实现哈希表所需的内存量,再加上存储桶的集合,再加上最大存储桶数(最坏情况是每个存储桶一个条目,则为40000),这是最坏的情况。您仍然需要管理分配桶(因此需要“动态分配”),并且由于它们没有足够的空间来放置它们,因此您需要能够随着它们的生长而随机移动它们。只是您自己在管理分配,所以“动态分配”是否由您决定。
如果知道哈希表的最大(或固定)大小,则可以非常静态地对其进行分配。
动态分配的主要原因是在运行时改变大小,并能够在函数之间传递结构的所有权。例如(并且它根本不与哈希表绑定,因此我只使用通用结构):
Item *GetItem() {
return new Item();
}
这将动态分配项目,并将其传递回调用方(以及所有权(管理其生命周期的责任))。避免动态分配的一种简单方法是:
Item *GetItem() {
Item item;
return &item;
}
不幸的是,该地址在返回时不可用,因为item
当时不在范围内,因此您可以通过以下方式阻止这种情况的发生:
Item *GetItem() {
static Item item;
return &item;
}
即使从函数返回后仍保留该对象,但有一个限制,即该对象只能有一个副本。如果您尝试从该函数中获取两项,它们将是同一项,除非您意识到这一点,否则您可能会遇到错误。
因此,我想说,只要您只需要一个哈希表,就可以通过具有静态哈希表来避免动态内存分配。
当然,除了单拷贝限制外,它还要求您分配所需的最大空间。这不是一个[[不必要一个坏主意(特别是如果它是固定大小的),但是可能会导致效率低下。
use
),因此开销相对较小。并且它使您能够在程序中具有多个哈希表。