开发者

Why does TObjectList<T>.Clear not free objects?

开发者 https://www.devze.com 2023-03-16 16:07 出处:网络
I just noticed that var ObjList : TObjectList <TMyObject>; ... ObjList := TObjectList <TMyObject>.Create (True);

I just noticed that

var
  ObjList : TObjectList <TMyObject>;
...
ObjList := TObjectList <TMyObject>.Create (True);
ObjList.Add (TMyObject.Create);
ObjList.Clear;

does not free the object. Looking at the source code it seems that no cnRemoved notification is triggered in Clear (inherited from TList <T>).

My question: Is this intentional? Is there any reason why one does not want to get these notifications in the case of Clear? Or can this be considered as a bug in the collection classes?

EDIT

Turns out that a I put the line

inherited Create;

on the top of TMyObject destructor, which was supposed to go into the constructor. This is why I got memory leaks reported that looked like the TObjectList was not freeing the items. And a look at the source convinced me (开发者_StackOverflowI was trapped by the Count property). Thanks for your help anyway!


The list frees owned objects when you call .Clear. You've got a testing error. The code sample below, written on Delphi XE, displays this:

Calling CLEAR
Object deleted.
Object deleted.
After CLEAR. Press ENTER to free L and Exit.

The code in TList<T>.Clear is deceiving, because Count is actually a property. Look at SetCount(), then look at DeleteRange() and you'll see the code for Notify(oldItems[i], cnRemoved) at the end of the DeleteRange procedure.


program Project3;

{$APPTYPE CONSOLE}

uses SysUtils, Generics.Collections;

type
  TDelObject = class
  public
    destructor Destroy;override;
  end;

{ TDelObject }

destructor TDelObject.Destroy;
begin
  WriteLn('Object deleted.');
  inherited;
end;

var L:TObjectList<TDelObject>;

begin
  L := TObjectList<TDelObject>.Create(True);
  L.Add(TDelObject.Create);
  L.Add(TDelObject.Create);
  WriteLn('Calling CLEAR');
  L.Clear;
  WriteLn('After CLEAR. Press ENTER to free L and Exit.');
  Readln;
  L.Free;
end.


TList<T>.Clear calls DeleteRange to do the work. The last part of DeleteRange runs around all the items calling Notify passing cnRemoved.

Your analysis of the code is thus incorrect. The cnRemoved notification is duly delivered and owned objects are freed.

0

精彩评论

暂无评论...
验证码 换一张
取 消