一、TList类
1.1 1.1 TList类的属性
由TList类的原码可以看到,TList类有如下几个特性:
property Capacity: Integer read FCapacity write SetCapacity;
property Count: Integer read FCount write SetCount;
property Items[Index: Integer]: Pointer read Get write Put; default;
property List: PPointerList read FList;
它们之间的关系如图:
1. 其中,值得注意的是当使用SetCount和SetCapacity函数时的各种情况;在SetCount中有这样一段代码:
if NewCount > FCount then
FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0)
else
for I := FCount - 1 downto NewCount do
Delete(I);
既是说,当NewCount > FCount时,将会把多余的空间置为空;否则,将删除(FCount - NewCount)的那些多余的Items.
2. 在SetCapacity函数中调用了这样一个函数:
ReallocMem(FList, NewCapacity * SizeOf(Pointer));
此函数有两个参数(var P: Pointer; Size: Integer),它将根据这两个参数的不同值做不同的处理:
(1)当p = nil,Size = nil时,不做任何处理;
(2)当p = nil,Size <> nil时, 将分配空间,把p指向该空间
(3)当p <> nil,Size = nil时, 将释放掉p所指向的空间。
(4)当p <> nil,Size <> nil时, ReallocMem函数将不会影响到原来已有的空间。
1.2 2.2 TList类的空间分配
TList类为了获得合适的容量,在请求增加容量时调用了Grow函数,此函数是根据你目前Capacity的大小来分配空间的;它的增长趋势是
Capacity = 0->4->8->12->12 + 16->28 + 16->...->76 + (Capacity div 4)->...
所以,当您分配一个合适的值给Capacity时,在调用Add方法时,就可以避免多次分配内存,有利于提高程序的性能。
1.3 2.3 TList类中Assign方法中的奇怪???
TList类中为了实现对象间的赋值,TList类实现了一个带缺省参数的方法procedure Assign(ListA: TList; AOperator: TListAssignOp = laCopy; ListB: TList = nil),而再看此方法的实现部分:
procedure TList.Assign(ListA: TList; AOperator: TListAssignOp; ListB: TList);
var
I: Integer;
LTemp, LSource: TList;
begin
if ListB <> nil then
begin
LSource := ListB;
Assign(ListA); // 看这段代码它递归调用了自己,你是否觉得奇怪呢?其实不然,它这里很巧妙的运用了递归。使得该方法
end // 实现了TListAssignOp = (laCopy, laAnd, laOr, laXor, laSrcUnique, laDestUnique)这么几种不
else // 同情况下对TList对象的赋值
LSource := ListA;
case AOperator of
laCopy:
begin
Clear;
Capacity := LSource.Capacity;
for I := 0 to LSource.Count - 1 do
Add(LSource[I]);
end;
......