Dynamic
arrays do not have a fixed size or length. Instead, memory for a dynamic array
is reallocated when you assign a value to the array or pass it to the SetLength
procedure. Dynamic-array types are denoted by constructions of the form
array of baseType
For
example,
var
MyFlexibleArray: array of Real;
declares a one-dimensional dynamic array of
reals. The declaration does not allocate memory for MyFlexibleArray. To
create the array in memory, call SetLength. For example, given the
declaration above,
SetLength(MyFlexibleArray,
20);
allocates an array of 20 reals, indexed 0
to 19. Dynamic arrays are always integer-indexed, always starting from 0.
Dynamic-array variables are implicitly pointers and are managed by the same reference-counting technique used for long strings. To deallocate a dynamic array, assign nil to a variable that references the array or pass the variable to Finalize; either of these methods disposes of the array, provided there are no other references to it. Dynamic arrays of length 0 have the value nil. Do not apply the dereference operator (^) to a dynamic-array variable or pass it to the New or Dispose procedure.
If X and Y are variables of the
same dynamic-array type, X := Y points X to the same array as Y. (There is no
need to allocate memory for X before performing this operation.) Unlike strings
and static arrays, dynamic arrays are not automatically copied before they are
written to. For example, after this code executes
var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := A;
B[0] := 2;
end;
the value of A[0] is 2. (If A and B were
static arrays, A[0] would still be 1.)
Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7) does not reallocate the array. Out-of-range indexes are not reported at compile time.
When dynamic-array variables are
compared, their references are compared, not their array values. Thus, after
execution of the code
var
A, B: array of Integer;
begin
SetLength(A, 1);
SetLength(B, 1);
A[0] := 2;
B[0] := 2;
end;
A = B returns False but A[0] = B[0]
returns True.
To
truncate a dynamic array, pass it to SetLength or Copy and assign
the result back to the array variable. (The SetLength procedure is
usually faster.) For example, if A is a dynamic array, A := SetLength(A, 0, 20)
truncates all but the first 20 elements of A.
Once a
dynamic array has been allocated, you can pass it to the standard functions Length,
High, and Low. Length returns the number of elements in
the array, High returns the array’s highest index (that is, Length - 1),
and Low returns 0. In the case of a zero-length array, High
returns -1(with the anomalous consequence that High < Low).
Note: In some function and
procedure declarations, array parameters are represented as array of baseType,
without any index types specified. For example,
function
CheckStrings(A: array of string): Boolean;
This
indicates that the function operates on all arrays of the specified base type,
regardless of their size, how they are indexed, or whether they are allocated
statically or dynamically. See Open array
parameters.
Multidimensional dynamic arrays
动态数组没有固定的尺寸或长度。取而代之的是,向动态数组赋值或把动态数组传递给SetLength过程时,动态数组的内存被重新分配。表示动态数组的结构具有如下形式
array of baseType
例如,
var
MyFlexibleArray: array of Real;
这里声明了一个一维的实数动态数组。声明并不为MyFlexibleArray变量分配内存。要为数组创建内存,则需要调用SetLength标准过程。例如,对于上面给出的声明,
SetLength(MyFlexibleArray,
20);
这里分配了一个20个实数的数组,索引从0到19。动态数组总是以整数作为索引,而且索引总是以0开始。
动态数组变量是一个隐含的指针,其管理机制与长串管理中使用的引用计数(reference-counting)技术相同。要释放动态数组,可以把空指针nil赋给引用数组的变量,或者把变量作为参数传递给标准过程Finalize;倘若对动态数组没有其他的引用,这两种方法都可以释放数组。长度为0的动态数组,其值为空指针nil。不要对动态数组变量使用解除参照指针的运算符(^),也不要把动态数组变量作为参数传递给标准过程New或Dispose。
如果X和Y是同一动态数组类型的变量,那么X := Y执行的操作是把X指向与Y相同的数组。(这里不需要在执行操作之前为X分配内存。)与串和静态数组不同,动态数组在数据写入之前不会被自动复制。例如,下列代码执行后
var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := A;
B[0] := 2;
end;
A[0]的值是2。(如果A和B是静态数组,那么此时A[0]仍为1。)
向动态数组索引赋值(如,MyFlexibleArray[2] := 7)时,不会重新分配数组。对于动态数组,超出范围的索引在编译时不会报告错误。
比较动态数组变量时,比较的是它们的引用,而不是数组的值。因此,下面的代码执行后
var
A, B: array of Integer;
begin
SetLength(A, 1);
SetLength(B, 1);
A[0] := 2;
B[0] := 2;
end;
表达式A = B返回False(因为此时A和B引用的是两个不同的动态数组),而表达式A[0] =
B[0]返回True。
要截断一个动态数组,可以将其作为参数传递给标准过程SetLength,或者传递给标准过程Copy并将结果赋给数组变量。(通常,使用SetLength过程会更快。)例如,如果A是一个动态数组,那么
SetLength(A, 20) 或 A := Copy(A, 0, 20) 执行的结果,即截去数组A中除前20个元素之外的所有元素。(显然,原文内容值得商榷。)
一旦一个动态数组被分配,就可以将其作为参数传递给标准函数Length、High、Low。Length返回数组中元素的个数,High返回数组的最大索引(即Length -
1),Low返回0。对于零长度的数组,High返回
-1(此时违背常规,有High < Low)。
注意:在一些函数和过程说明中,数组参数以array of baseType的形式出现,而没有任何指定的索引类型。例如,
function
CheckStrings(A: array of string): Boolean;
这表示该函数作用于所有指定基类型(这里的基类型是string)的数组,而不管其尺寸大小,不管其索引类型,也不管是静态分配还是动态分配。见开放的数组参数。