Выбрать главу

type

 bigArray: array[1..32000] of integer;  {или ^double, или что-то еще}

 pMyArray: ^bigArray;

затем распределите сам массив:

getMem (pMyArray, sizeof(integer) * n);

где n — количество элементов. После этого вы можете ссылаться на элементы массива следующим образом:

pMyArray^[51]

Не забудьте освободить массив с помощью FreeMem после того, как вы его использовали.

Изменить размер массива, определить новый указатель, перераспределить или обменяться с другим массивом можно так:

pTemp: ^bigArray;

getMem(pTemp, sizeof(integer) * newnumelements);

memcopy(pTemp, pMyArray, sizeof(integer)*n);

{n – количество элементов в pMyArray}

freeMem(pMyArray, sizeof(integer)*n);

pMyArray := pTemp;

4. Если вам необходим многомерный массив чисел, скомбинируйте технику, описанную в пункте (3), с функцией распределения, описанной в пункте (2).

5. Если для вашего массива необходим участок памяти больше чем 64K, вам необходимо разработать список указателей на участки памяти, но эта тема выходит за рамки данной статьи.

Лично я инкапсулировал все в своем объекте. Я использую, как я это называю, «Basic String Object» (BSO), базовый строковый объект, который осуществляет динамическое распределение и освобождение памяти для строк любого размера. Непосредственно это PChar, указывающий на распределенную память. У меня существует два внешних свойства: AsString и AsPChar. Также у меня есть различные свойства и методы, позволяющие иметь различные способы доступа и манипулировать строками.

Я написал свои собственные malloc(), calloc() и realloc(), используя частные методы объекта TString для сканирования распределенной памяти. Это классно работает, когда мне нужно «захватить» блок памяти.

С помощью двух методов я могу распределить необходимую мне память (блоками, так что это не занимает много процессорного времени), и освобождать ее (когда существует определенный резерв – и снова так, чтобы не тратить много процессорного времени).

О другой идее я уже рассказывал (открытый массив). Если вам нужна проверка выхода за границы и/или динамическое изменение размера массива, вы можете использовать метод, аналогичный методу работы со строковым объектом (описанный мною выше), но вам необходимо будет интегрировать свойство-массив по умолчанию, чтобы иметь к нему простой доступ. Это позволит вам иметь индексы и использовать нужный вам тип.

TMyDynamicObject =

 …

 PROPERTY Array[idx:LONGINT]:TMyType READ GetArray WRITE PutArray DEFAULT;

VAR Mine :TMyDynamicObject;

Mine := TMyDynamicObject.Create;

FOR i := 10 TO 20 DO Mine[i] := {значение}

{ЧУДОВИЩНАЯ РАСТРАТА ПАМЯТИ - если вы действительно используете такие большие массивы и хэш-таблицы }

Mine[-100000] := {значение}

Mine[+100000] := {значение}

Если в вашем распоряжении находится «редкозаполненный» массив, использование хэш-таблицы дало бы существенный выигрыш. Я преобразую индексные значения в строки, а все остальное перепоручаю TStrings, но не из-за того, что я такой ленивый, а из-за того, что он сделает это лучше меня, мне нужно всего лишь осуществить преобразование в строки.

Для того, чтобы хранить все, что вы хотите, вы можете использовать TList (или TStringList.Objects)! TList.Items хранят указатели на объекты или записи, но они ничего не могут сделать с ними, поэтому вы можете привести их к типу longint, и больше о них не беспокоиться! Вот пример хранения в TList списка целых:

var

 aList: TList;

 I : Integer;

 L : Longint;

begin

 aList := TList.Create;

 L := 93823;

 aList.Add(Pointer(L));

 aList.Add(Pointer(83293));

 for I := 1 to aList.Count do L := L + Longint(aList.Items[I-1]);

 aList.Free;

end;

В TList и TStringList вы можете иметь до 16380 элементов. А теперь обещанный пример того, как можно хранить в TList записи (или объекты), вернее, указатели на них:

type

 PMyRec = TMyRec;

 TMyRec = record

  Name: string[40];

  Addr : string[25];

  Comments: string;

  salary: Double;

 end;

var

 aList: TList;

 aRecPtr: PMyRec;

 I : Integer;

begin

 aList := TList.Create;

 New(aRecPtr);

 with aRecPtr^ do begin

  Name := 'Валентин';

  Addr := 'неизвестен';

  Comments := 'Автор Советов по Delphi';

  Salary := 999000.00;

 end;

 aList.Add(aRecPtr);

 aList.Add(…);

 …

 for I := 1 to aList.Count do begin

  aRecPtr := PMyRec(aList.Items[I-1]);

  {что-то делаем с записью}

 end;

 {теперь избавляемся от всех записей и самого списка-объекта}

 for I := 1 to aList.Count do Dispose(PMyRec(aList.Items[I-1]));

 aList.Free;