2011-08-03 141 views
1

我需要从数组中删除特定的元素,该数组将被动态调整大小,以便存储未知数量的元素与realloc从c数组中删除元素

为了控制所分配的存储器,并定义的元素,我有其他两个变量:

double *arr = NULL; 
int elements = 0; 
int allocated = 0; 

一些元件之后被放置在阵列中,我可能需要删除其中的一些。我找到的所有文本都使用memmove,并通过删除的元素数减少变量。

我的疑问是,如果这种方法是安全和有效的。

+1

你认为'memmove'的哪个部分是不安全或效率低下的。你选择用C写作,现在你担心内存操作的安全性了? –

+1

你确实意识到realloc对整个内存系统的健康状况(碎片,分配/复制/空闲时间等等)是多么糟糕...... –

+0

安全我的意思是说我担心内存泄漏。因为我不知道'memmove'的工作原理。我不知道被移除的元素会发生什么(它不是一个指针,所以它不需要'free'调用),如果数组真的被调整大小(因为我减少了'elements'和'allocated'计数器 – Wanderson

回答

4

我觉得这是最有效的功能,你可以使用(memcpy不是一个选项)关于安全 - 你将需要确保这些参数都OK,否则不好的事情会发生:)

2

使用memmove肯定是有效的,并且不比遍历数组安全明显不那么安全。要知道实现的实际安全程度,我们需要查看代码,特别是调用memmove调用以及realloc的返回结果是如何被检查的。

如果你得到你的的memmove错误的,或者不检查任何realloc的回报,期待崩溃。

1

原则上,假设你正确地计算你的地址和长度,你可以使用memmove,但是请注意,如果你用更高索引的元素重写一个或多个元素,并且这些被覆盖的元素是包含分配内存指针的结构,你可能会产生泄漏。

不好意思,你必须先照顾好你正在覆盖的元素,然后才能使用memmove。你如何处置他们取决于他们代表什么。如果它们仅仅是包含指向其他结构的指针的结构体,但它们不“拥有”分配的内存,则什么都不会发生。如果指针“拥有”内存,则必须首先释放它。

+0

这是一个结构数组只包含简单的双数据,而不是指针。 – Wanderson

+0

然后就没有问题了。 –

0

可以通过数据分区来提高memmove()realloc()的性能。通过数据分区,我的意思是使用多个数组块而不是一个大数组。

除了memmove(),我发现内存交换是有效的方式。但是有缺点。数组顺序可以用这种方式改变。

int remove_element(int*from, int total, int index) { 
     if(index != (total-1)) 
       from[index] = from[total-1]; 
     return total-1; // return the number of elements 
} 

有趣的是,数组可以通过索引随机访问。随机移除元素也可能影响其他元素的索引。如果在数组循环遍历中完成此删除操作,那么重新排序可能会导致意外的结果。

解决该问题的一种方法是使用is_blank遮罩阵列并推迟移除。可以创建稀疏数组。但也可以在空白位置添加新元素时填充它。

再一次,可以在下面的高效交换算法中使数组变得紧凑。

int sparse_to_compact(int*arr, int total, int*is_valid) { 
     int i = 0; 
     int last = total - 1; 
     // trim the last blank elements 
     for(; last >= 0 && is_blank[last]; last--); // trim blank elements from last 

     // now we keep swapping the blank with last valid element 
     for(i=0; i < last; i++) { 
       if(!is_blank[i]) 
         continue; 
       arr[i] = arr[last]; // swap blank with the last valid 
       last--; 
       for(; last >= 0 && is_blank[last]; last--); // trim blank elements 
     } 
     return last+1; // return the compact length of the array 
} 

请注意,上面的算法使用交换,它会改变元素顺序。可能是在数组的某些循环操作之外使用它是首选/安全的。如果元素的索引保存在某个地方,它们也需要更新/重建。