-
Привет!
Динамический массив так, как он явлен в FPC, не совсем устраивает, ибо нужно явно указывать тип данных. TList, как я понял, является списком указателей, что слишком универсально, IMHO. Написал свой простенький инструментик для хранения нетипизированных данных - надо только указать размер элемента. Ну и приведение типов при работе с элементами массива. И задумался - мож, я изобрёл велосипед?
С уважением.
-
> Динамический массив так, как он явлен в FPC, не совсем устраивает, > ибо нужно явно указывать тип данных.
-----------------
> надо только указать размер элемента. Ну и приведение типов > при работе с элементами массива.
А разница?
-
Разница? Я же не знаю размер типа, который будет храниться в массиве во время выполнения. Соответственно, встаёт проблема индексации элементов массива. К примеру, вот я объявляю массив: myarray : array of byte; А затем структуру mystruc : record
...
end;
mydata : mystruc;
И как же мне запихнуть переменную mydata в массив myarray?
-
А разве myarray: array of mystruc нельзя ???
-
> myarray: array of mystruc
Можно, только в рантайме массив может "поменять" свою специализацию и хранить данные другой структуры. Поэтому неясно, как индексировать данные, тип которых на этапе компиляции неизвестен.
-
> Можно, только в рантайме массив может "поменять" свою специализацию > и хранить данные другой структуры.
Зачем? > Поэтому неясно, как индексировать данные, тип которых на > этапе компиляции неизвестен.
Любой типизированный указатель может использоваться как массив. Индексация начинается с нуля, как и в динамических. var A : PInteger;
begin
GetMem (A, sizeof(Integer)*10);
A[2] := 10;
A[3] := A[2]+12;
WriteLn (A[3])
end
-
> > Можно, только в рантайме массив может "поменять" свою > специализацию > > и хранить данные другой структуры. > > Зачем?
А получается более абстрактная вещь, чем динамический массив. Удобно - потому что не нужно на каждый тип делать свой массив. Можно, конечно, использовать что-то вроде TList - но меня, честно, жаба задушила на каждую вершину (или грань) свой Pointer иметь :) У меня есть куча разнотипных данных (вершины, грани, материалы и т.п.), которые хранятся, по сути, в однотипных массивах (хех, у них только типы элементов разные). Плюс в рантайме получается один загрузчик для всех этих типов - ему до лампочки, что хранить - лишь бы размер элемента был известен.
> Любой типизированный указатель может использоваться как > массив. Индексация начинается с нуля, как и в динамических. >
Да, это забавная штука в плане упрощения синтаксиса. И setLength не нужен уже :)
-
> И setLength не нужен уже :)
Только память нужно ручками выделять.
-
Необязательно... Создаём массив байт, далее создаём типизированный указатель на этот массив и... (:
-
П7 (28.09.05 20:59) [8] Необязательно... Создаём массив байт, далее создаём типизированный указатель на этот массив и... (:
Так это и есть "выделение памяти".
-
Do you mean "generics" that will be supported in .net 2? in that case it will be supported in D2007 (not yet in D2006, at least not in beta) and eventually in D2007 win32 and therefore in Freepascal 3.0 ;)
-
Тут наткнулся на подобный класс... Полностью приводить не буду - в сети он есть, достаточно скачать исходники к книге "The tomes of Delphi algorithms and data structures" - ToDADS_source.zip ...
TtdRecordList = class
private
FActElemSize : integer;
FArray : PAnsiChar;
FCount : integer;
FCapacity : integer;
FElementSize : integer;
FIsSorted : boolean;
FMaxElemCount: integer;
FName : TtdNameString;
...
constructor TtdRecordList.Create(aElementSize : integer);
begin
inherited Create;
FActElemSize := aElementSize;
FElementSize := ((aElementSize + 3) shr 2) shl 2;
FMaxElemCount := 65535 div FElementSize;
FMaxElemCount := MaxInt div integer(FElementSize);
FIsSorted := true;
end;
...
procedure TtdRecordList.Delete(aIndex : integer);
begin
if (aIndex < 0) or (aIndex >= Count) then
rlError(tdeIndexOutOfBounds, 'Delete', aIndex);
dec(FCount);
if (aIndex < Count) then
System.Move((FArray + (succ(aIndex) * FElementSize))^,
(FArray + (aIndex * FElementSize))^,
(Count - aIndex) * FElementSize);
if (Count <= 1) then
FIsSorted := true;
end;
...
procedure TtdRecordList.Insert(aIndex : integer; aItem : pointer);
begin
if (aItem = nil) then
rlError(tdeNilItem, 'Insert', aIndex);
if (aIndex < 0) or (aIndex > Count) then
rlError(tdeIndexOutOfBounds, 'Insert', aIndex);
if (Count = Capacity) then
rlExpand;
if (aIndex < Count) then
System.Move((FArray + (aIndex * FElementSize))^,
(FArray + (succ(aIndex) * FElementSize))^,
(Count - aIndex) * FElementSize);
System.Move(aItem^,
(FArray + (aIndex * FElementSize))^,
FActElemSize);
inc(FCount);
FIsSorted := (Count = 1);
end;
...
|