【问题标题】:Do I need to realloc after memmove when remove an element from dynamic array?从动态数组中删除元素时,是否需要在 memmove 之后重新分配?
【发布时间】:2016-04-02 05:10:42
【问题描述】:

我正在使用 C 语言实现 ArrayList。ArrayList 存储指针 (void*),这意味着 ArrayList 是指针的动态数组。这里我如何从 ArrayList 中删除一个元素:

typedef struct
{
    void* ptr; // pointer of array (beginning)
    int length; // pointer count
}ArrayList;

void ArrayList_Remove(ArrayList *list, int index)
{
    memmove(
        list->ptr + (sizeof(void*) * index),
        list->ptr + (sizeof(void*) * (index + 1)),
        (list->length - index) * sizeof(void*)
    );
    list->length--;
    // Do I need to realloc list->ptr to free space?
    // list->ptr = realloc(list->ptr, list->length * sizeof(void*));
}

正如我在代码中评论的那样,我需要重新分配list->ptrmemmove 吗?

【问题讨论】:

  • 注意:不能对void *的类型应用指针运算。
  • @BLUEPIXY 那么如何通过偏移量获取指针呢?也许是指针数组(void**)?
  • 使用GCC的扩展是没有问题的。通常它会转换为char*。是的,如果void **p = malloc(size * sizeof(void*));
  • 如果使用void**,(sizeof(void*)除外)sizeof(void*) * index --> index
  • 一种常见的模式是跟踪长度和分配的长度。添加元素时,只要长度和分配的长度相等,才需要重新分配。当你删除一个元素时,你可以选择是否重新分配,通常你只会重新分配分配的长度比使用的长度大很多。

标签: c arrays pointers memory


【解决方案1】:

memmove() 不会释放任何内存。

您可以使用realloc(),或者在您需要添加/插入项目时留下额外的空间。这需要在你的结构中添加一个额外的成员来跟踪分配的大小。

此外,如果您计划动态添加插入项,您可能希望以更大的块增加缓冲区,以防止每次都调用realloc()。通常这是在一定大小(例如 16 - 32 - 64 - 1024)的 2 次方中完成的。之后,每次以固定大小扩展缓冲区。

【讨论】:

    【解决方案2】:

    第一件事:memmove 根本不参与内存分配。它只是做它应该做的,移动(可能重叠)部分内存。

    在您的示例中,重新分配数组并非绝对必要。这主要取决于是否删除了这么多元素,以便有足够的可用空间供重用。如果您觉得这确实相关,那么您下面的 realloc 语句看起来是正确的。但请记住,如果由于堆碎片问题仅删除每个数组的几个元素,则未分配的空间可能根本不可用。

    【讨论】:

    • 我明白你的意思 :) 另外,感谢您指出内存碎片
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-17
    • 2017-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-06
    • 2011-08-27
    相关资源
    最近更新 更多