2009-02-12 2 views
9

Angenommen meine Delphi-Klassen wie folgt aussehen:Wie sollte ich ein Array von Objekten in einem Delphi 7 Destruktor freigeben?

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. 

richtig zu reinigen, was in der destructor gehen sollte? Ist es genug zu tun SetLength(SubInfo,0), oder muss ich durchlaufen und frei jedes TMySubInfo? Muss ich überhaupt etwas tun?

Antwort

12

Sie müssen jedes erstellte Objekt durchlaufen und freigeben.

Sie müssen wissen, dass das Deklarieren eines Arrays von TMySubInfo die Objekte tatsächlich nicht erstellt. Sie müssen sie später erstellen.

Ich würde stattdessen eine TList für einen dynamischeren Ansatz verwenden. Sie können sogar eine TObjectList verwenden, die alle ihre Elemente freigibt, wenn die Liste freigegeben wird.

+0

Ja, ich rufe TMySubInfo.Create in einer Schleife, um sie zu erstellen. Sobald ich sie erstellt habe, muss ich keine hinzufügen oder entfernen, weshalb ich ein einfaches Array gewählt habe. – Blorgbeard

+0

Auch angenommen, dass ich sie in einer Schleife freigebe, muss ich auch SetLength (0) danach? – Blorgbeard

+3

Sie müssen SetLength nicht aufrufen. Dynamische Arrays werden automatisch bereinigt, sobald der Referenzzähler auf 0 geht. –

2

Für jeden neuen sollte es einen freien geben.

+1

oder Erstellen in Delphi –

+0

Eigentlich nicht in Delphi.Zuerst werden Schnittstellen gezählt, und ihnen zugewiesene Objekte werden automatisch freigegeben. Zweitens, Datensätze können mit 'Create' initialisiert werden, aber Sie' Free' nicht. – user

3

Wenn Sie die Objekte über Konstruktoraufrufe erstellt haben, müssen Sie Free anrufen, um sie freizugeben. Wenn nicht, dann nicht.

9

sollten Sie jedes Element freizugeben, wie diese

destructor TMyInfo.Destroy; 
var 
    I: Integer; 
begin 
    for I:= Low(SubInfo) to High(SubInfo) do 
    SubInfo[I].Free; 
    SetLength(SubInfo, 0); 
    inherited; 
end; 
+3

SetLength (SubInfo, 0); ist optional, aber ja, guter Code. –

6

befreien Sie die Objekte auf die gleiche Weise sie zugeordnet. Wenn Sie den Wert eines Elements durch Aufrufen des Konstruktors einer Klasse zugewiesen haben, geben Sie das Objekt frei, auf das von diesem Element verwiesen wird.

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

Das Syntax in Delphi 2005 eingeführt verwendet Wenn Sie eine ältere Version haben, verwenden Sie eine explizite Schleife-Regelgröße:

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

Sie brauchen nicht SetLength am Ende zu nennen. Ein dynamisches Array-Feld wie SubInfo wird automatisch freigegeben, wenn das Objekt zerstört wird. Es funktioniert genauso wie Interface-, String- und Variant-Felder.

5

Einverstanden mit allen oben genannten Vorschlägen, aber ich möchte eine (zugegebenermaßen etwas anale) Empfehlung hinzufügen, dass Sie die FreeAndNil() - Prozedur immer der Free-Methode vorziehen.

Früher oder später werden Sie versehentlich auf ein Objekt zugreifen, das Sie bereits freigegeben haben. Wenn Sie die Angewohnheit von FreeAndNil-ing haben, erhalten Sie sofort ein A/V in der Zeile, die das Problem enthält. Wenn Sie das Objekt lediglich freigeben, erhalten Sie wahrscheinlich später einen mysteriösen und anscheinend nicht verbundenen Fehler ...

Dies mag im Kontext eines Destruktors wie hier obsessiv erscheinen. Ok, es ist ein bisschen, aber entweder tut man es überall oder gar nicht.

0

Können Sie nicht Finalize verwenden?

+0

Finalize wird keine referenzierten Objekte oder Dispose New'ed pointer usw. –

4

Es ist auch anal, aber wie in der umgekehrten Reihenfolge der Schöpfung, zum Beispiel zu befreien:

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

I Schöpfung und Zerstörung als parethesis anzuzeigen(), obwohl es litte tatsächliche Ausführung diference macht. Bri

Verwandte Themen