Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Delete doing anything at all in this procedure?

In a project I received and currently I am working on, I've seen this code more than a few times when releasing items from a list.

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

What is the purpose of that Delete(0) after using Free?

Is it a better option to call FreeAndNil() for the elements and then for the list, and not using Delete, which I can't understand why previous developers used it there.

like image 538
Diego Rueda Avatar asked Dec 08 '22 08:12

Diego Rueda


1 Answers

Delete is necessary to remove the first item from the list. That way, the second item becomes the first, and the loop continues until no items are left. All Delete does, is removing the item, while Free takes care of freeing the object to which that item pointed. FreeAndNil won't help, since you would still have nil in the list, instead of removing it (it probably won't compile anyway, since Item[i] is a probably a property).

This loop can be quite inefficient, though. If this is a TList, or any other class that uses a similar array-wrapping approach, then this causes a lot of moving of memory. When you delete the first item, all the other items are actually moved in memory.

A better solution. This one is faster, because it doesn't do a big number of array-shifting.

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

Other solutions (as per comments)

Probably just as fast as the one above. Also doesn't need array shifting, and, more importantly, you won't have stale items in your list, because they are deleted right away.

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

Which can alternatively be written as:

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

Note that in a multi-threaded environment this might still cause trouble, since freeing and deleting the item isn't atomic. There are multiple ways to solve that, but I think it's out of the scope of this answer.

Even better than the solutions above: Use a TObjectList (if it isn't already an objectlist). TObjectList has a property OwnsObject, indicating whether the objectlist should take care of cleaning up the objects in it. If that property is True, you can just call Clear, and it will do that freeing and deleting for you.

like image 177
GolezTrol Avatar answered Jan 05 '23 10:01

GolezTrol