删除是否在此过程中执行任何操作?

时间:2014-03-25 20:15:45

标签: delphi memory-management

在我收到的一个项目中,我目前正在处理这个项目,从列表中释放项目时,我已经看过几次这段代码了。

while Count > 0 do
  begin
   Items[0].Free;
   Delete(0);
 end;

使用Delete(0)之后Free的目的是什么?

为元素调用FreeAndNil(),然后为列表调用Delete是不是更好的选择,我无法理解为什么以前的开发人员在那里使用它。

2 个答案:

答案 0 :(得分:12)

删除列表中的第一项是必要的。这样,第二个项目成为第一个,循环继续,直到没有项目。所有Delete都会删除该项,而Free负责释放该项指向的对象。 FreeAndNil不会有帮助,因为你在列表中仍然会有nil,而不是删除它(它可能无论如何都不会编译,因为Item[i]可能是属性)。

但是,这个循环可能效率很低。如果这是一个TList,或任何其他使用类似数组包装方法的类,那么这会导致大量的内存移动。当您删除第一个项目时,所有其他项目实际上都在内存中移动。

更好的解决方案。 这个更快,因为它不会进行大量的阵列转换。

for i := 0 to Count - 1 do
  Items[i].Free;
Clear;

其他解决方案(根据评论)

可能和上面一样快。也不需要数组移位,更重要的是,您不会在列表中包含过时的项目,因为它们会立即被删除。

while Count > 0 do
begin
  Items[Count-1].Free;
  Delete(Count-1);
end;

也可以写成:

for i := Count - 1 downto 0 do
begin
  Items[i].Free;
  Delete(i);
end;

请注意,在多线程环境中,这可能仍然会带来麻烦,因为释放和删除项目不是原子的。有多种方法可以解决这个问题,但我认为这超出了这个答案的范围。

甚至比上述解决方案更好: 使用TObjectList(如果它还不是对象列表)。 TObjectList有一个属性OwnsObject,指示对象列表是否应该清理其中的对象。如果该属性为True,您只需致电Clear,它就会为您释放和删除。

答案 1 :(得分:2)

此代码正在清除列表,同时销毁其成员。

  • Free的调用会破坏该项目。
  • Delete的调用会从列表中删除对该项目的引用。

如果没有调用Delete,则循环永远不会终止。请注意循环条件while Count > 0。循环的每次迭代都将Count减1,直到列表为空时达到零。

在现代Delphi中,列表可能会被TObjectList<TMyObject>替换,列表将OwnsObjects设置为True。然后,对列表中Clear的单个调用将释放所有成员,并清除列表。