2009-02-12 18 views
9

Supongamos que mi clases de Delphi se ven así:¿Cómo debo liberar una matriz de objetos en un destructor 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. 

Para limpiar correctamente, lo que debe ir en el destructor? ¿Es suficiente hacer SetLength(SubInfo,0), o necesito abrir y cerrar cada TMySubInfo? ¿Debo hacer algo?

Respuesta

12

Debe recorrer y liberar cada objeto creado.

Debe saber que declarar una matriz de TMySubInfo en realidad no crea los objetos. Tienes que crearlos más tarde.

Usaría un TList en cambio para un enfoque más dinámico. Incluso podría usar TObjectList que pueda liberar todos sus elementos cuando se libere la lista.

+0

Sí, estoy llamando a TMySubInfo.Crear en un bucle para crearlos. Una vez creado, sin embargo, no necesito agregar ni eliminar ninguno, por lo que elegí una matriz simple. – Blorgbeard

+0

Además, suponiendo que los libere en un bucle, ¿necesito SetLength (0) también, luego? – Blorgbeard

+3

No es necesario llamar a SetLength. Las matrices dinámicas se limpian automáticamente una vez que el recuento de referencias va a 0. –

2

Para cada nuevo debería ser gratis.

+1

o Crear en Delphi –

+0

En realidad, no en Delphi.En primer lugar, las interfaces se cuentan por referencia y los objetos asignados se liberan automáticamente. En segundo lugar, los registros se pueden inicializar usando 'Crear', pero no los 'Libre'. – user

3

Si creó los objetos mediante llamadas de constructor, debe realizar llamadas a Libre para liberarlos. Si no, no lo haces.

9

Usted debe liberar cada elemento, como este

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); es opcional, pero sí, buen código. –

6

Usted liberar los objetos de la misma manera que ellos asignados. Si asignó el valor de un elemento llamando al constructor de una clase, libere el objeto al que hace referencia ese elemento.

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

que utiliza la sintaxis introducida en Delphi 2005. Si tiene una versión anterior, utilice una variable de control de bucle explícito:

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

No es necesario llamar SetLength al final. Un campo de matriz dinámica como SubInfo se libera automáticamente cuando se destruye el objeto. Funciona igual que los campos de interfaz, cadena y Variante.

5

De acuerdo con todas las sugerencias anteriores, pero quiero agregar una recomendación (por cierto algo anal) que siempre llama al procedimiento FreeAndNil() con preferencia al método Free.

Tarde o temprano, accidentalmente accederá a un objeto que ya ha liberado. Si tiene el hábito de FreeAndNil-ing todo, entonces obtiene una a/v inmediata en la línea que contiene el problema. Si simplemente liberaste el objeto, es probable que recibas una falla misteriosa y aparentemente desconectada más tarde ...

Esto podría parecer obsesivo en el contexto de un destructor, como aquí. Ok, es un poco, pero cualquiera lo hace en todas partes o no lo hace en absoluto.

0

¿No puedes usar Finalize?

+0

Finalizar no hará referencia a objetos gratis o Eliminar punteros nuevos, etc. –

4

También es anal, pero igual de libres en el orden inverso a la creación, por ejemplo:

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

que ver la creación y la destrucción como parethesis() a pesar de que hace litte diference ejecución real. Bri

Cuestiones relacionadas