Почему TObjectList <T>.Clear не свободные объекты? - PullRequest
5 голосов
/ 29 июня 2011

Я только что заметил, что

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

не освобождает объект.Глядя на исходный код, кажется, что cnRemoved не запускается уведомление в Clear (унаследовано от TList <T>).

Мой вопрос: Это намеренно?Есть ли причина, по которой никто не хочет получать эти уведомления в случае Clear?Или это можно рассматривать как ошибку в классах коллекции?

РЕДАКТИРОВАТЬ

Оказывается, что я поставил строку

inherited Create;

вершина деструктора TMyObject, который должен был войти в конструктор.Вот почему мне сообщили об утечках памяти, которые выглядели так, как будто TObjectList не освобождает предметы.И взгляд на источник убедил меня (я был пойман в ловушку свойством Count).В любом случае спасибо за вашу помощь!

Ответы [ 2 ]

15 голосов
/ 29 июня 2011

Список освобождает принадлежащие объекты при вызове .Clear.У вас есть ошибка тестирования.Пример кода ниже, написанный на Delphi XE, показывает это:

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

Код в TList<T>.Clear обманчив, потому что Count на самом деле является свойством.Посмотрите на SetCount(), затем посмотрите на DeleteRange(), и вы увидите код для Notify(oldItems[i], cnRemoved) в конце процедуры DeleteRange.


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.
8 голосов
/ 29 июня 2011

TList<T>.Clear звонит DeleteRange, чтобы сделать работу.Последняя часть DeleteRange охватывает все элементы, вызывающие Notify, передавая cnRemoved.

Таким образом, ваш анализ кода неверен.Уведомление cnRemoved доставлено должным образом, а принадлежащие ему объекты освобождены.

...