在我收到的一个项目中,我目前正在处理这个项目,从列表中释放项目时,我已经看过几次这段代码了。
while Count > 0 do
begin
Items[0].Free;
Delete(0);
end;
使用Delete(0)
之后Free
的目的是什么?
为元素调用FreeAndNil()
,然后为列表调用Delete
是不是更好的选择,我无法理解为什么以前的开发人员在那里使用它。
答案 0 :(得分:12)
删除列表中的第一项是必要的。这样,第二个项目成为第一个,循环继续,直到没有项目。所有Delete
都会删除该项,而Free
负责释放该项指向的对象。 FreeAndNil不会有帮助,因为你在列表中仍然会有nil
,而不是删除它(它可能无论如何都不会编译,因为Item[i]
可能是属性)。
更好的解决方案。 这个更快,因为它不会进行大量的阵列转换。
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
的单个调用将释放所有成员,并清除列表。