Как освободить массив объектов в деструкторе Delphi 7? - PullRequest
9 голосов
/ 13 февраля 2009

Предположим, мои классы Delphi выглядят так:

interface
type

    TMySubInfo = class
    public
        Name : string;
        Date : TDateTime;
        Age  : Integer;
    end;

    TMyInfo = class
    public
        Name : string;
        SubInfo : array of TMySubInfo;
        destructor Destroy; override;
    end;

implementation

    destructor TMyInfo.Destroy;
    begin
      // hmmm..
    end;

end.

Чтобы правильно очистить, что должно идти в деструкторе? Достаточно ли сделать SetLength(SubInfo,0), или мне нужно пройти и освободить каждый TMySubInfo? Нужно ли вообще что-то делать?

Ответы [ 8 ]

12 голосов
/ 13 февраля 2009

Вам нужно перебрать и освободить каждый созданный объект.

Вы должны знать, что объявление массива TMySubInfo на самом деле не создает объекты. Вы должны создать их позже.

Я бы использовал TList вместо этого для более динамичного подхода. Вы даже можете использовать TObjectList, который может освободить все свои элементы, когда список будет освобожден.

9 голосов
/ 13 февраля 2009

Вы должны освободить каждый предмет, как это

destructor TMyInfo.Destroy;
var
  I: Integer;
begin
  for I:= Low(SubInfo) to High(SubInfo) do
   SubInfo[I].Free;
  SetLength(SubInfo, 0); 
  inherited;
end;
6 голосов
/ 13 февраля 2009

Вы освобождаете объекты так же, как вы их распределили. Если вы присвоили значение элемента, вызвав конструктор класса, то освободите объект, на который ссылается этот элемент.

destructor TMyInfo.Destroy;
var
  info: TMySubInfo;
begin
  for info in SubInfo do
    info.Free;
  inherited;
end;

Использует синтаксис, введенный в Delphi 2005. Если у вас более старая версия, используйте явную переменную контроля цикла:

var
  i: Integer;
begin
  for i := 0 to High(SubInfo) do
    SubInfo[i].Free;

Вам не нужно звонить SetLength в конце. Поле динамического массива, такое как SubInfo, освобождается автоматически при уничтожении объекта. Он работает так же, как интерфейс, строка и поля Variant.

5 голосов
/ 13 февраля 2009

Согласен со всеми вышеперечисленными предложениями, но я хочу добавить (предположительно несколько анальный) рекомендацию, чтобы вы всегда вызывали процедуру FreeAndNil () вместо предпочтения метода Free.

Рано или поздно вы случайно получите доступ к объекту, который вы уже освободили. Если у вас есть привычка FreeAndNil - все, то вы получите немедленный A / V на строке, которая содержит проблему. Если вы просто Free'd объект, через некоторое время вы, вероятно, получите таинственный и явно не связанный сбой ...

Это может показаться навязчивым в контексте деструктора, как здесь. Хорошо, это немного, но кто-то делает это везде или нет вообще.

4 голосов
/ 15 сентября 2009

Это также анально, но нравится бесплатно в обратном порядке к созданию, например:

For I := List.Count-1 downto 0 do
  List[I].Free;

Я рассматриваю создание и разрушение как parethesis (), хотя это делает разницу между фактическим исполнением. Bri

3 голосов
/ 13 февраля 2009

Если вы создали объекты с помощью вызовов конструктора, вам нужно сделать вызовы Free, чтобы освободить их. Если нет, то нет.

2 голосов
/ 13 февраля 2009

За каждое новое должно быть бесплатно.

0 голосов
/ 15 сентября 2009

Разве вы не можете использовать Завершить ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...