2009-02-12 6 views
9

mes classes Delphi Supposons ressemblent à ceci:Comment libérer un tableau d'objets dans un destructeur Delphi 7?

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. 

Pour bien nettoyer, ce qui devrait aller dans le destructor? Est-il suffisant de faire SetLength(SubInfo,0), ou dois-je faire une boucle et libérer chaque TMySubInfo? Ai-je besoin de faire quoi que ce soit?

Répondre

12

Vous devez parcourir et libérer chaque objet créé.

Vous devez savoir que déclarer un tableau de TMySubInfo ne crée pas réellement les objets. Vous devez les créer plus tard.

J'utiliserais plutôt un TList pour une approche plus dynamique. Vous pouvez même utiliser une TObjectList qui peut libérer tous ses éléments lorsque la liste est libérée.

+0

Oui, j'appelle TMySubInfo.Create dans une boucle pour les créer. Une fois créé, cependant, je n'ai pas besoin d'ajouter ou de supprimer un - c'est pourquoi j'ai choisi un simple tableau. – Blorgbeard

+0

Aussi, en supposant que je les libère dans une boucle, ai-je besoin de SetLength (0) aussi, après? – Blorgbeard

+3

Il n'est pas nécessaire d'appeler SetLength. Les tableaux dynamiques sont automatiquement nettoyés dès que le nombre de références est passé à 0. –

2

Pour chaque nouveau, il devrait y avoir un libre.

+1

ou Créer dans Delphi –

+0

En fait, pas dans Delphi.Premièrement, les interfaces sont comptées et les objets qui leur sont attribués sont automatiquement libérés. Deuxièmement, les enregistrements peuvent être initialisés en utilisant 'Create', mais vous ne les 'Free'. – user

3

Si vous avez créé les objets via des appels de constructeur, vous devez appeler Free pour les libérer. Sinon, vous ne le faites pas.

9

Vous devriez libérer chaque élément, comme celui-ci

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); est optionnel, mais oui bon code. –

6

Vous libérez les objets de la même manière que vous les alloué. Si vous avez affecté la valeur d'un élément en appelant le constructeur d'une classe, libérez l'objet référencé par cet élément.

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

Cette syntaxe utilise introduite en Delphi 2005. Si vous avez une ancienne version, utilisez une variable boucle de contrôle explicite:

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

Vous n'avez pas besoin d'appeler SetLength à la fin. Un champ de tableau dynamique tel que SubInfo est libéré automatiquement lorsque l'objet est détruit. Il fonctionne de la même manière que les champs interface, chaîne et Variant.

5

D'accord avec toutes les suggestions ci-dessus, mais je tiens à ajouter une recommandation (certes un peu anale) que vous appelez toujours la procédure FreeAndNil() de préférence à la méthode Free.

Tôt ou tard, vous accéderez accidentellement à un objet que vous avez déjà libéré. Si vous avez l'habitude de FreeAndNil-ing tout, alors vous obtenez un a/v immédiat sur la ligne qui contient le problème. Si vous avez simplement libéré l'objet, vous aurez probablement un échec mystérieux et apparemment non connecté quelque temps plus tard ...

Cela peut sembler obsessionnel dans le contexte d'un destructeur, comme ici. Ok, c'est un peu, mais soit on le fait partout ou pas du tout.

0

Ne pouvez-vous pas utiliser Finalize?

+0

Finaliser ne sera pas gratuit objets référencés ou Dispose New'ed pointeurs etc. –

4

Il est également anal, mais comme à libérer dans l'ordre inverse à la création, par exemple:

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

je l'ai vue la création et la destruction comme parethesis() bien qu'il rend l'exécution réelle litte diference. Bri

Questions connexes