从Delphi支持内建各种类型的动态数组。与静态数组的区别在于数组的长度可以变化。
一、动态数组的声明
1、 一种方式首先定义动态数组的结构的类,再通过类声明动态数据
type
TBytes = array of Byte;
TBytesArray = array of TBytes;
TStrDA = array of string;
TDA = array[0..9] of array of string;
var A:TBytes;
B:TDA;
2、Var直接声明带数据结构的动态数组
1、一维数组
var A : array of integer; // 动态数组定义时不定维数
2、多维数组
var B : array of array of integer; // 二维数组
var C : array of array of array of integer; // 三维数组
3、多维数组单元类型
var A : array[0.3] of integer; // 动态数组类型整数
var B : array of array of string; // 动态数组类型字符串
var C : array of Double; // 动态数组类型Double
二、初始化
1、资源字符和Const字符和数组,可加入动态数组
resourcestring
SA = 'abc';
SD = 'def';
const
C: array[1..2, 1..10] of Byte =
( (1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
BoolChars: array[boolean] of char = ('F', 'T');
2、直接赋值
var
B: TBytes = [1, 2, 3, 4];
C: TBytesArray = [[1, 2, 3], [4,5,6]];
D: TStrDA = ['ABC', 'DEF'];
E: TStrDA = [['A1','B1'],['A2','B2'],['A3','B3']];
F: TDA = [ Sabc, Sdef ];
三、动态数组的操作函数:
1.设置数组大小,可以任意缩减或增加数组大小
Procedure SetLength(var S ; NewLength : integer);
2.取出连续元素,复制给另一个数组变量
Function Copy(s;Index,Count : integer) : array ;
3.取得数组大小及上下限
Function Length(s):integer;
Function High(x):integer;
Function Low(x):integer;
注意不加const或var修饰的动态数组会被作为形参传递。
动态数组用const修饰并不意味着你不能修改数组里的元素。
High函数调用了Length 函数,所以我们在获取数组上限时直接用 Length(s) 函数。
4、动态数组的释放
一般没必要手动释放, 动态数组离开作用域会自释放。但养成释放是一个好的习惯。
动态数组释放,就在动态数据不再使用,应与创建在同一层,代码结尾时,通过下列三个函数释放:
var arr: array of Integer;
begin
SetLength(arr,10);
arr := nil; // 释放方法一
SetLength(arr, 0); // 释放方法二
Finalize(arr); // 释放方法三
end;
四、动态数组的结构
动态数组的内存空间中占用4个字节。 动态数组在内存中的分配表如下:
偏移量 内容
-8 32-bit 引用计数
-4 32-bit 数组长度
0..数组长度 * (元素尺寸) - 1 数组元素 元素尺寸=Sizeof(元素类型)
根据上面的分配情况,可以得到如下结果:
如果我们想要清空一个动态数组只需要把“数组长度”和“引用计数”清空即可。
五、高版本动态数组的改进
高版本Delphi,动态数组操作时不现要求Setlength,设置动态数组的长度。可以直接执行的类似字符串的操作:
1、B:=[1, 2, 3, 4]; // 直接赋值
2、B := B + [5, 6, 7]; // 合并
3、Insert([6, 7, 8], B, 5); // 将[6, 7, 8],插入B的5位置上
4、Delete(B, 1, 3); // 删除B数组中,位置1起始3个元素
5、Concat([1,2,3,4],[5,6,7]); // 合并
六、动态数据实例
//例1:
var StrArr: array of String;
begin
SetLength(StrArr,6); // 分配6个元素位置: 0-5
StrArr[0] := 'ABCDEFG';
ShowMessage(StrArr[0]); // 读写与静态数组一样
StrArr := nil;
end;
//例2. 动态多维数组:
var Arr: array of array of Integer; //定义多维数组
begin
SetLength(Arr,5,5); // 分配空间
Arr[0,3] := 100; // 赋值
ShowMessage(IntToStr(Arr[0,3])); // 取值
end;
//例3. 动态数组的引用:
var Arr1,Arr2: array of Integer;
a: array[0..1] of Integer;
begin
SetLength(Arr1,6);
Arr1[5] := 100;
Arr2 := Arr1; // Arr2 引用了 Arr1
ShowMessage(IntToStr(Arr2[5])); // 100
ShowMessage(IntToStr(Length(Arr2))); // Arr2 维数也会是 6
ShowMessage(IntToStr(SizeOf(Arr1))); //4, 其实动态数组是个指针
ShowMessage(IntToStr(SizeOf(Arr2))); //4
Arr2[5] := 99; //现在它们指向同一个数组, 改变这个就是改变那个
ShowMessage(IntToStr(Arr1[5])); //99
Arr1 := nil; //释放其中一个指针, 数组继续存在
ShowMessage(IntToStr(Arr2[5])); // 99
end;
--------------------------------------------------------------------------------
//例4. 数组 Copy <1>:
var Arr1,Arr2: array of Integer;
begin
SetLength(Arr1,6);
Arr1[5] := 100;
Arr2 := Copy(Arr1); // 数组 Copy
end;
--------------------------------------------------------------------------------
//例5. 数组 Copy <2>:
var
Arr1,Arr2: array of Integer;
i: Integer;
begin
SetLength(Arr1,6);
for i := Low(Arr1) to High(Arr1) do // 给每个元素赋值
Arr1[i] := i+1;
Arr2 := Copy(Arr1,1,3); // Copy 下标2开始,共3个 即第2..4个元素
end;
--------------------------------------------------------------------------------
//例6. 变体数组(伴有效率问题)
var Arr: array of Integer;
begin
Arr := varArrayCreate([0,3],varInteger);
ShowMessage(IntToStr(Length(Arr)));
Arr := VarArrayOf([1,2,3,4]);
ShowMessage(IntToStr(Arr[0]));
end;