Вот "демо-модуль", демонстрирующий три различных способа (далеко не все)
создания динамических массивов. Все три способа для распределения достаточного
количества памяти из кучи используют GetMem, tList используют для добавления
элементов в список массива и используют tMemoryStream для того, чтобы
распределить достаточно памяти из кучи и иметь к ней доступ, используя поток.
Старый добрый GetMem вполне подходит для такой задачи при условии, что массив не
слишком велик (<64K).
PS. Я не стал ловить в коде исключения (с помощью блоков Try...Finally},
которые могли бы мне помочь выявить ошибки, связанные с распределением памяти. В
реальной системе вы должны быть уверены в своем грациозном владении
низкоуровневыми операциями с памятью.
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}{ Форма, демонстрирующая различные методы создания массива с }{ динамически изменяемым размером. Разместите на форме четыре кнопки,}{ компоненты ListBox и SpinEdit и создайте, как показано ниже, }{ обработчики событий, возникающие при нажатии на кнопки. Button1, }{ Button2 и Button3 демонстрируют вышеуказанных метода. Button4 }{ очищает ListBox для следующего примера. }{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}unit Dynarry1;
interfaceuses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Spin;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
SpinEdit1: TSpinEdit;
ListBox1: TListBox;
Button4: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure Button4Click(Sender: TObject);
private{ Private declarations }public{ Public declarations }end;
var
Form1: TForm1;
implementation{$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 dobegin{ Распределяем уникальный экземпляр данных }
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 dobegin
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;
end.
Код, предоставленный, демонстрирует три способа создания динамических массивов в Delphi. Каждый метод использует функцию GetMem для выделения памяти из кучи и затем манипулирует массивом с помощью различных техник.
Вот разбивка каждого события клика кнопки:
Button1Click: Этот метод создает массив из 1000 элементов типа SomeType, который определен как целое число. Массив выделяется с помощью GetMem, и его размер определяется значением в контроле SpinEdit. Затем массив заполняется значениями от 1 до указанного размера, и содержимое отображается в списке.
Button2Click: Этот метод создает динамический список (связанный список) с помощью класса tList. Он выделяет память для каждого элемента с помощью функции New, заполняет список значениями от 1 до указанного размера и затем отображает содержимое в списке. Когда закончено, он освобождает каждый элемент с помощью Dispose и наконец освобождает список сам с помощью Free.
Button3Click: Этот метод использует поток памяти (tMemoryStream) для создания динамического массива. Он выделяет пространство для массива, установив размер потока, записывает значения в поток с помощью Write и затем читает обратно значения с помощью Read. Содержимое отображается в списке.
Button4Click: Этот метод просто очищает содержимое списка, что полезно для сброса отображения перед созданием нового динамического массива.
Код демонстрирует три различных подхода к управлению памятью:
Использование GetMem для выделения фиксированного блока памяти (Button1)
Использование New и Dispose для управления отдельными объектами в связанном списке (Button2)
Использование потока памяти (tMemoryStream) для динамического выделения и управления памятью (Button3)
В целом, рекомендуется использовать подход, который лучше всего подходит к вашим конкретным требованиям. Например, если вам нужно создать массив с фиксированным размером, использование GetMem может быть более эффективно. Если вам нужно создать динамический список, использование tList или другого реализации связанного списка может быть более подходящим.
Что касается обработки ошибок, рекомендуется поймать и обработать исключения, которые могут возникнуть при операциях управления памятью. В этом коде автор не включил обработчики исключений, но в реальном приложении вам обычно нужно обеспечить, чтобы ваш код был устойчивым и мог обрабатывать неожиданные ошибки гладко.
Данная статья демонстрирует три различных метода создания динамических массивов на языке Delphi, используя GetMem, tList и tMemoryStream соответственно.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.