Вот "демо-модуль", демонстрирующий три различных способа (далеко не все) создания динамических массивов. Все три способа для распределения достаточного количества памяти из кучи используют GetMem, tList используют для добавления элементов в список массива и используют tMemoryStream для того, чтобы распределить достаточно памяти из кучи и иметь к ней доступ, используя поток. Старый добрый GetMem вполне подходит для такой задачи при условии, что массив не слишком велик (<64K).
PS. Я не стал ловить в коде исключения (с помощью блоков Try...Finally}, которые могли бы мне помочь выявить ошибки, связанные с распределением памяти. В реальной системе вы должны быть уверены в своем грациозном владении низкоуровневыми операциями с памятью.
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} { Форма, демонстрирующая различные методы создания массива с } { динамически изменяемым размером. Разместите на форме четыре кнопки,} { компоненты ListBox и SpinEdit и создайте, как показано ниже, } { обработчики событий, возникающие при нажатии на кнопки. Button1, } { Button2 и Button3 демонстрируют вышеуказанных метода. Button4 } { очищает ListBox для следующего примера. } {++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++} unit Dynarry1;
{$R *.DFM} Type pSomeType = ^SomeType; SomeType = Integer;
procedure TForm1.Button1Click(Sender: TObject); Type pDynArray = ^tDynArray; tDynArray = Array[1..1000] Of SomeType; Var DynArray : pDynArray; I : Integer; begin { Распределяем память } GetMem ( DynArray, SizeOf(SomeType) * SpinEdit1.Value ); { Пишем данные в массив } For I := 1 to SpinEdit1.Value Do DynArray^[I] := I; { Читаем данные из массива } For I := SpinEdit1.Value DownTo 1 Do ListBox1.Items.Add ( 'Элемент ' + IntToStr(DynArray^[I]) ); { Освобождаем память } FreeMem ( DynArray, SizeOf(SomeType) * SpinEdit1.Value ); end;
procedure TForm1.Button2Click(Sender: TObject); Var List : tList; Item : pSomeType; I : Integer; begin { Создаем список } List := tList.Create; { Пишем данные для списка } For I := 1 to SpinEdit1.Value Do Begin { Распределяем уникальный экземпляр данных } New ( Item ); Item^ := I; List.Add ( Item ); End; { Читаем данные из списка - базовый индекс списка 0, поэтому вычитаем из I единицу } For I := SpinEdit1.Value DownTo 1 Do ListBox1.Items.Add ( 'Элемент ' + IntToStr(pSomeType(List.Items[I-1])^) ); { Освобождаем лист } For I := 1 to SpinEdit1.Value Do Dispose ( List.Items[I-1] ); List.Free; end;
procedure TForm1.Button3Click(Sender: TObject); Var Stream : tMemoryStream; Item : SomeType; I : Integer; begin { Распределяем память потока } Stream := tMemoryStream.Create; Stream.SetSize ( SpinEdit1.Value ); { Пишем данные в поток } For I := 1 to SpinEdit1.Value Do { Stream.Write автоматически отслеживает позицию записи, поэтому при записи данных за ней следить не нужно } Stream.Write ( I, SizeOf ( SomeType ) ); { Читаем данные из потока } For I := SpinEdit1.Value DownTo 1 Do Begin Stream.Seek ( (I-1) * SizeOf ( SomeType ), 0 ); Stream.Read ( Item, SizeOf ( SomeType ) ); ListBox1.Items.Add ( 'Элемент ' + IntToStr(Item) ); End; { Освобождаем поток } Stream.Free; end;
procedure TForm1.Button4Click(Sender: TObject); begin ListBox1.Items.Clear; end;