Arrays dinamicos en delphi

Tengo 2 preguntas que espero que me sepas responder :)
¿1 - Como trata los arrays dinamicos el delphi?, es decir, ¿cuándo reserva
memoria para las filas/columnas del array (mediante setLenght) como lo hace?
¿Las guarda como listas dinámicas o reserva memoria en la heap?
¿2 - El delphi tiene recolector de memoria?, he leido que para destruir
la matriz solo hay que asignarle el valor nil, ¿entonces qué pasa con la
memoria a la que apuntaba?, sobretodo si la matriz contenia algun objeto q haya que destruir...

1 Respuesta

Respuesta
1
Muy buena pregunta, para la 1ra-
Segun lei por ahi, cuando reservas la memoria con SetLengh() lo hace por la cantidad del array
Por ejemplo,
var MyFlexibleArray: array of Real;
Declara en array de reales de una dimencion. Esto no asigna la memoria para MyFlexibleArray.
Para crear el array en memoria, podes usar, SetLength.
SetLength(MyFlexibleArray, 20);
Asigna un array de 20 reales, comenzando en la posicion 0 a 19.
Lo reserva de la memoria heap
Tambien podes hacerlo con Getmen
Myarray := GetMem(rows * cols * sizeof(byte,word,single,double etc)
uso esta funcion para ver si dispongo de la memoria necesaria
function AllocArray(var V : pointer; const N : longint) : Boolean;
begin {allocate memory for array V of size N}
try
GetMem(V, N);
except
ShowMessage('ERROR Asignando Memoria. Tamaño:' + IntToStr(N));
Result := True;
exit;
end;
FillChar(V^, N, 0);
Result := False;
end;
Para la otra pregunta, es correcto lo que decis, si asignas a al matriz el valor nil, pero si queres destruir algun objeto tenes que usar Finalize, y de esta forma destruis todo.
Podes usar tambien Freemem
Otras funciones interesantes son ReallocMem, Initialize, StrAlloc, StrDispose.
Todo lo que esta en la heap se maneja automáticamente.
Te paso una Unit y como usarla
(*
--
-- Unit to create two very simple dynamic array classes
-- TDynaArray : a one dimensional array
-- TDynaMatrix : a two dimensional dynamic array
--
*)
unit DynArray;
INTERFACE
uses
SysUtils;
Type
TDynArrayBaseType = double;
Const
vMaxElements = (High(Cardinal) - $f) div sizeof(TDynArrayBaseType);
{= guarantees the largest possible array =}
Type
TDynArrayNDX = 1..vMaxElements;
TArrayElements = array[TDynArrayNDX] of TDynArrayBaseType;
{= largest array of TDynArrayBaseType we can declare =}
PArrayElements = ^TArrayElements;
{= pointer to the array =}
EDynArrayRangeError = CLASS(ERangeError);
TDynArray = CLASS
Private
fDimension : TDynArrayNDX;
fMemAllocated : word;
Function GetElement(N : TDynArrayNDX) : TDynArrayBaseType;
Procedure SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType);
Protected
Elements : PArrayElements;
Public
Constructor Create(NumElements : TDynArrayNDX);
Destructor Destroy; override;
Procedure Resize(NewDimension : TDynArrayNDX); virtual;
Property dimension : TDynArrayNDX
read fDimension;
Property Element[N : TDynArrayNDX] : TDynArrayBaseType
read GetElement
write SetElement;
default;
END;
Const
vMaxMatrixColumns = 65520 div sizeof(TDynArray);
{= build the matrix class using an array of TDynArray objects =}
Type
TMatrixNDX = 1..vMaxMatrixColumns;
TMatrixElements = array[TMatrixNDX] of TDynArray;
{= each column of the matrix will be a dynamic array =}
PMatrixElements = ^TMatrixElements;
{= a pointer to an array of pointers... =}
TDynaMatrix = CLASS
Private
fRows : TDynArrayNDX;
fColumns : TMatrixNDX;
fMemAllocated : longint;
Function GetElement( row : TDynArrayNDX;
column : TMatrixNDX) : TDynArrayBaseType;
Procedure SetElement( row : TDynArrayNDX;
column : TMatrixNDX;
const NewValue : TDynArrayBaseType);
Protected
mtxElements : PMatrixElements;
Public
Constructor Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX);
Destructor Destroy; override;
Property rows : TDynArrayNDX
read fRows;
Property columns : TMatrixNDX
read fColumns;
Property Element[row : TDynArrayNDX; column : TMatrixNDX] : TDynArrayBaseType
read GetElement
write SetElement;
default;
END;
IMPLEMENTATION
(*
--
-- TDynArray methods
--
*)
Constructor TDynArray.Create(NumElements : TDynArrayNDX);
BEGIN {==TDynArray.Create==}
inherited Create;
fDimension := NumElements;
GetMem( Elements, fDimension*sizeof(TDynArrayBaseType) );
fMemAllocated := fDimension*sizeof(TDynArrayBaseType);
FillChar( Elements^, fMemAllocated, 0 );
END; {==TDynArray.Create==}
Destructor TDynArray.Destroy;
BEGIN {==TDynArray.Destroy==}
FreeMem( Elements, fMemAllocated );
inherited Destroy;
END; {==TDynArray.Destroy==}
Procedure TDynArray.Resize(NewDimension : TDynArrayNDX);
BEGIN {TDynArray.Resize==}
if (NewDimension < 1) then
raise EDynArrayRangeError.CreateFMT('Index out of range : %d', [NewDimension]);
Elements := ReAllocMem(Elements, fMemAllocated, NewDimension*sizeof(TDynArrayBaseType));
fDimension := NewDimension;
fMemAllocated := fDimension*sizeof(TDynArrayBaseType);
END; {TDynArray.Resize==}
Function TDynArray.GetElement(N : TDynArrayNDX) : TDynArrayBaseType;
BEGIN {==TDynArray.GetElement==}
if (N < 1) OR (N > fDimension) then
raise EDynArrayRangeError.CreateFMT('Index out of range : %d', [N]);
result := Elements^[N];
END; {==TDynArray.GetElement==}
Procedure TDynArray.SetElement(N : TDynArrayNDX; const NewValue : TDynArrayBaseType);
BEGIN {==TDynArray.SetElement==}
if (N < 1) OR (N > fDimension) then
raise EDynArrayRangeError.CreateFMT('Index out of range : %d', [N]);
Elements^[N] := NewValue;
END; {==TDynArray.SetElement==}
(*
--
-- TDynaMatrix methods
--
*)
Constructor TDynaMatrix.Create(NumRows : TDynArrayNDX; NumColumns : TMatrixNDX);
Var col : TMatrixNDX;
BEGIN {==TDynaMatrix.Create==}
inherited Create;
fRows := NumRows;
fColumns := NumColumns;
{= acquire memory for the array of pointers (i.e., the array of TDynArrays) =}
GetMem( mtxElements, fColumns*sizeof(TDynArray) );
fMemAllocated := fColumns*sizeof(TDynArray);
{= now acquire memory for each column of the matrix =}
for col := 1 to fColumns do
BEGIN
mtxElements^[col] := TDynArray.Create(fRows);
inc(fMemAllocated, mtxElements^[col].fMemAllocated);
END;
END; {==TDynaMatrix.Create==}
Destructor TDynaMatrix.Destroy;
Var col : TMatrixNDX;
BEGIN {==TDynaMatrix.Destroy;==}
for col := fColumns downto 1 do
BEGIN
dec(fMemAllocated, mtxElements^[col].fMemAllocated);
mtxElements^[col].Free;
END;
FreeMem( mtxElements, fMemAllocated );
inherited Destroy;
END; {==TDynaMatrix.Destroy;==}
Function TDynaMatrix.GetElement( row : TDynArrayNDX;
column : TMatrixNDX) : TDynArrayBaseType;
BEGIN {==TDynaMatrix.GetElement==}
if (row < 1) OR (row > fRows) then
raise EDynArrayRangeError.CreateFMT('Row index out of range : %d', [row]);
if (column < 1) OR (column > fColumns) then
raise EDynArrayRangeError.CreateFMT('Column index out of range : %d', [column]);
result := mtxElements^[column].Elements^[row];
END; {==TDynaMatrix.GetElement==}
Procedure TDynaMatrix.SetElement( row : TDynArrayNDX;
column : TMatrixNDX;
const NewValue : TDynArrayBaseType);
BEGIN {==TDynaMatrix.SetElement==}
if (row < 1) OR (row > fRows) then
raise EDynArrayRangeError.CreateFMT('Row index out of range : %d', [row]);
if (column < 1) OR (column > fColumns) then
raise EDynArrayRangeError.CreateFMT('Column index out of range : %d', [column]);
mtxElements^[column].Elements^[row] := NewValue;
END; {==TDynaMatrix.SetElement==}
END.
--------------------------------------------------------------------------------
----Test program for the DynArray unit----
--------------------------------------------------------------------------------
uses DynArray, WinCRT;
Const
NumRows : integer = 7;
NumCols : integer = 5;
Var
M : TDynaMatrix;
row, col : integer;
BEGIN
M := TDynaMatrix.Create(NumRows, NumCols);
for row := 1 to M.Rows do
for col := 1 to M.Columns do
M[row, col] := row + col/10;
writeln('Matrix');
for row := 1 to M.Rows do
BEGIN
for col := 1 to M.Columns do
write(M[row, col]:5:1);
writeln;
END;
writeln;
writeln('Transpose');
for col := 1 to M.Columns do
BEGIN
for row := 1 to M.Rows do
write(M[row, col]:5:1);
writeln;
END;
M.Free;
END.
Bueno espero que te sirva.
Saludos
Luis
Desde Argentina
q:p
Peazo respuesta!!Chico te voy a meter en mi lista de expertos favoritos :) Muuuuuuchas gracias!Es la mejor respuesta que he obtenido !
Un saludo, Alicia desde España

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas