Динамические массивы

Вверх  Предыдущий  Следующий

Начиная с версии 1.1, Free Pascal также поддерживает, динамические массивы: В этом случае диапазон массива не указывается, как в следующем примере:

Type

TByteArray = Array of Byte;

При объявлении переменной типа динамический массив начальная длина массива равна нулю. Фактическая длина массива должна быть установлена стандартной функцией SetLength, которая выделит память необходимую для размещения элементов массива в куче. Следующий пример установит длину массива равную 1000:

Var

A : TByteArray;

 

begin

SetLength(A,1000);

После вызова SetLength, допустимыми индексами массива будут числа от 0 до 999: индексация массива всегда начинается с нуля.

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

Также есть возможность изменить размер массива: в этом случае будет сохранено настолько много элементов сколько поместится в новом размере массива. Размер массива может быть установлен в ноль, это эффективный способ сбросить переменную.

Попытка получить доступ к элементу массива с индексом, выходящим за границы объявленного диапазона, всегда генерирует ошибку периода выполнения.

Для динамических массивов ведется подсчет ссылок: присвоение одной переменной типа динамический массив, другой переменной, позволит обеим переменным указывать на тот же самый массив. В отличие от AnsiStrings, присвоение значения одному элементу массива будет отражено и в другом: не делается никакой копии массива при записи. Рассмотрите следующий пример:

Var

A,B : TByteArray;

 

begin

SetLength(A,10);

A[0]:=33;

B:=A;

A[0]:=31;

После второго присвоения первый элемент в B будет также содержать 31.

Это также можно заметить по выводу следующего примера:

program testarray1;

 

Type

TA = Array of array of Integer;

 

var

A,B : TA;

I,J : Integer;

 

begin

Setlength(A,10,10);

For I:=0 to 9 do For J:=0 to 9 do A[I,J]:=I*J;

For I:=0 to 9 do

  begin

    For J:=0 to 9 do Write(A[I,J]:2,' ');

    Writeln;

  end;

B:=A;

Writeln;

For I:=0 to 9 do For J:=0 to 9 do A[9-I,9-J]:=I*J;

For I:=0 to 9 do

  begin

    For J:=0 to 9 do Write(B[I,J]:2,' ');

    Writeln;

  end;

end.

Выводом этой программы будет матрица чисел, а затем будет выведена такая же матрица, но зеркально.

DynDim

Как отмечалось ранее, для динамических массивов ведется подсчет ссылок: если в одном из предыдущих примеров A выйдет за границы области а B нет, то массив ещё не будет освобожден: счетчик ссылок АB) уменьшится на 1. Как только счетчик ссылок достигнет нуля, память, выделенная для содержания массива, освобождается.

Вызов SetLength установит счетчик ссылок на указанный массив в 1, если он больше, то после вызова SetLength переменные динамического массива больше не будут указывали на одну и ту же память.

program testunique;

 

Type

TA = array of Integer;

 

var

A,B : TA;

I : Integer;

begin

Setlength(A,10);

For I:=0 to 9 do A[I]:=I;

B:=A;

SetLength(B,6);

A[0]:=123;

For I:=0 to 5 do Writeln(B[I]);

end.

Также возможно скопировать и/или изменить размер массива с помощью стандартной функции Copy, которая действует как функция копирования для строк:

program testarray3;

 

Type

TA = array of Integer;

 

var

A,B : TA;

I : Integer;

begin

Setlength(A,10);

For I:=0 to 9 do A[I]:=I;

B:=Copy(A,3,6);

For I:=0 to 5 do Writeln(B[I]);

end.

Функция Copy скопирует 6 элементов массива в новый массив. Начиная с элемента по индексу 3 (то есть четвертого элемента) массива.

Функция Length возвратит число элементов в массиве. Функция Low для динамического массива будет всегда возвращать 0, а функция High возвратит значение Length-1, то есть, значение самого большого позволенного индекса массива.