Как мне освободить содержимое TList?
У меня есть этот код в Delphi 4. Я создал 10 объектов типа T_Charge
(см. ниже), который я добавил к TList
по имени myList
, T_Charge
тип имеет ссылки на три объекта типа T_Platte
(увидеть ниже).
Как правильно освободить всю память всех 10 объектов? Итак, для каждого объекта я хочу освободить память P1
, P2
, P3
, F_Treated
и так далее, а также память о myCharge
сам. Я пробовал обо всем, но продолжаю получать ошибки.
procedure Test;
var
myList: TList;
myCharge: T_Charge;
begin
myList := TList.Create;
for i := 0 to 9 do
begin;
myCharge := T_Charge.Create(...);
myList.Add(myCharge);
end;
...
end;
type
T_Platte = class(TObject)
private
F_Nummer : Integer;
F_Los : Integer;
F_Dicke : Real;
F_Lange : Real;
F_Breite : Real;
F_QuenchCode : Integer;
F_Geschwindigkeit : Real;
F_Menge : Integer;
F_MengeInLos : Integer;
F_Treated : Boolean;
public
constructor Create(inNummer, inLos: Integer; inDicke, inLange, inBreite, inGeschwindigkeit : Real; inQuenchCode,inMenge: Integer; inTreated: Boolean); overload;
constructor Create(inPlatte: T_Platte); overload;
destructor Destroy; override;
property Nummer: Integer read F_Nummer write F_Nummer;
property Los: Integer read F_Los write F_Los;
property Dicke: Real read F_Dicke write F_Dicke;
property Lange: Real read F_Lange write F_Lange;
property Breite: Real read F_Breite write F_Breite;
property QuenchCode : Integer read F_QuenchCode write F_QuenchCode;
property Geschwindigkeit: Real read F_Geschwindigkeit write F_Geschwindigkeit;
property Menge: Integer read F_Menge write F_Menge;
property MengeInLos: Integer read F_MengeInLos write F_MengeInLos;
property Treated: Boolean read F_Treated write F_Treated;
function getPlattenRecord: string;
end; // class T_Platte
T_Charge = class(TObject)
private
F_P1 : T_Platte;
F_P2 : T_Platte;
F_P3 : T_Platte;
F_Treated : Boolean;
F_Vmin : Real;
F_Qty : Integer;
F_RelationNext : Boolean;
public
constructor Create(inP1, inP2, inP3 : T_Platte; inTreated: Boolean; inVmin: Real; inQty: Integer; inRelationNext: Boolean); overload;
constructor Create(inCharge : T_Charge); overload;
destructor Destroy; override;
property P1: T_Platte read F_P1 write F_P1;
property P2: T_Platte read F_P2 write F_P2;
property P3: T_Platte read F_P3 write F_P3;
property Treated : Boolean read F_Treated write F_Treated;
property Vmin : Real read F_Vmin write F_Vmin;
property Qty : Integer read F_Qty write F_Qty;
property RelationNext : Boolean read F_RelationNext write F_RelationNext;
function getChargeRecord: string;
end; // class T_Charge
constructor T_Platte.Create(inNummer, inLos: Integer; inDicke, inLange, inBreite, inGeschwindigkeit: Real; inQuenchCode,inMenge: Integer; inTreated: Boolean);
begin
F_Nummer := inNummer;
F_Los := inLos;
F_Dicke := inDicke;
F_Lange := inLange;
F_Breite := inBreite;
F_Geschwindigkeit := inGeschwindigkeit;
F_QuenchCode := inQuenchCode;
F_Menge := inMenge;
F_MengeInLos := 0;
F_Treated := inTreated;
end;
constructor T_Charge.Create(inP1, inP2, inP3 : T_Platte; inTreated: Boolean; inVmin: Real; inQty: Integer; inRelatio nNext: Boolean);
begin
F_P1 := T_Platte.Create(inP1);
F_P2 := T_Platte.Create(inP2);
F_P3 := T_Platte.Create(inP3);
F_Treated := inTreated;
F_Vmin := inVmin;
F_Qty := inQty;
F_RelationNext := inRelationNext;
end;
6 ответов
Чтобы освободить объекты списка, создайте свой список и переопределите TList.Notify().
procedure THotFixList.Notify(Ptr: Pointer; Action: TListNotification);
begin
inherited;
if Action = lnDeleted then
Tobject(Ptr).Free;
end;
Это обеспечит освобождение ваших объектов всякий раз, когда вы вызываете TLIst.Delete, TList.Clear, TList.Free, без необходимости каждый раз повторять список самостоятельно.
Добавьте следующее в деструктор для T_Charge
:
destructor T_Charge.Destroy;
begin
F_P1.Free;
F_P2.Free;
F_P3.Free;
// Other code as needed
inherited;
end;
Прежде чем освободить свой список, выполните цикл и удалите каждый T_Charge
:
for i := 0 to myList.Count - 1 do
TObject(myList[i]).Free; // This will free the inner `T_Platt3`
// each `T_Charge` contains.
Не забудьте набрать приведение предметов, так как они содержат указатель без типа!
for i := 0 to myList.Count - 1 do
begin
T_Charge(myList[i]).Free; // Type cast
end;
В частности, когда список должен содержать экземпляры классов, я думаю, что вы должны использовать TObjectList
для этой цели ( TObjectList). Позвоните конструктору TObjectList
с Create(True)
который сообщает списку освободить все содержащиеся в нем экземпляры классов после уничтожения списка или удаления из него элемента. Тем не менее, как уже упоминалось в ответе Кена Уайта, вам все еще нужно освободить F_P1 и т. Д. В деструкторе T_Charge.
Небольшое знание классов: TList vs TObjectList
TList держит Pointers
поэтому не имеет ни малейшего представления о том, как освободить TObject
хранится
TObjectList hols TObjects
, так может освободить их и делает это автоматически
Мое лучшее, что я могу сказать: использовать TObjectList
вместо TList
как ваш базовый класс или объявление типа.
Образцы:
Wrong: TMyListOfObjects=class(TList) ...
Good: TMyListOfObjects=class(TObjectList) ...
Wrong: MyListOfObjects:TList;
Good: MyListOfObjects:TObjectList;
Замечания: TList
объявляется на единицу classes
а также TObjectList
объявлен на Contnrs
, что заставляет так много людей использовать TList
и ничего не знаю о TObjectList
(также я, прежде чем я прочитал о TObjectList
в Интернете некоторое время назад).
Перед уничтожением myList вам необходимо:
for i := 0 to myList.Count - 1 do
begin;
TObject(myList[i]).Free
end;
В деструкторе для T_Charge вам нужно освободить F_P1, F_P2 и F_P3.