码迷,mamicode.com
首页 > Windows程序 > 详细

Delphi小谈之TList

时间:2015-07-29 00:43:50      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:

转载自:http://blog.csdn.net/jqandjq/article/details/5429137

 

  在我刚接触TList的时候,TList搞得我迷雾重重,都是Capacity属性惹的祸。我查了Delphi的帮助,它说Capacity是Tlist的最大容量,又在什么地方说MaxInt div 4是TList的最大容量。最后我搞明白了,Capacity是临时的,MaxInt div 4 才是真正的最大容量。只要你的内存受得了就行,算起来一共是4G。

  在TList内部有一个FList指针指向一个Pointer数组,Capacity就是这个数组的大小。奇怪的是Capacity是可写的。我当时就在想,如果一直使用Add直到超出Capacity的范围,会怎么样呢?为了解决这个问题,我特地打开了TList的代码,结果发现如下几行(注释是我自己加的):

function TList.Add(Item: Pointer): Integer;
begin
    {返回Item所在的位置}
    Result:= FCount;
    {如果FList数组被填满了装不下新的Item,那么TList自动增加Capacity,也就是FList指向的数组的大小}
    if Result = FCapacity then
        Grow;
    {扩大了FList的大小之后,就能把Item放进数组了}
    FList^[Result]:= Item;
    Inc(FCount);
    if Item <> nil then
        Notify(Item, InAdded);
    {给TList一个信号,通知TList已经加上一个新的Item}
end;

procedure TList.Grow;
var
    Delta: Integer;
begin
    {增加的规则是,如果数量小于或等于8,那么增加4;那么增加在8之上,小于或等于64,那么增加16;如果数量比64还大,那么一次增加大约1/4的空间}
    if FCapacity > 64 then
        Delta:= FCapacity div 4
    else
        Delta:= 4;
    {改变数组的大小}
    SetCapacity(FCapacity + Delta);
end;

  既然Capacity会自动增加,那么还要Capacity干什么呢?还不如使用链表。不过我后来意识到,在使用链表额时候,取得某个位置的指针比数组困难,要用比较费时间的循环。TList刚好解决了这个问题。我们既可以把TList当成数组,也可以把它当成链表。

 

TList的Items属性和List属性            

  TList除了保存的对象是指针之外,其他地方都与TStringList很像,所以下面只介绍两者的不同之处。我们同样可以使用TList或者TList.Items获得某一位置的指针。如果嫌TList.Items是属性没有效率的话,这里还有一个List属性,指向内部的FList,可以这样使用:

TList.List^

 

TList的First和Last属性              

  TList提供了First和Last两个属性,分别返回第一个和最后一个指针。

 

TList的Delete和Remove方法           

  TList也提供了一个Remove方法。与Delete不同的是,Delete删除的是已知位置的指针,Remove删除的是已知指针。只要TList包含有你想删除的指针,你就可以使用

Remove(Pointer);

  Remove的返回值是指针在还没有被删除之前的位置,使用方法如下

procedure Delete(Index: Integer);
function Remove(Item: Pointer): Integer;

  

Tlist的Pack方法                  

  TList还有一个Pack方法。它能够把所有不是nil的指针聚在一起,同时把Count的值改变,这样,所有没有用的指针就会被删除,但是并不会减少Capacity。如果你想把没有用的空间都释放的话,可以把Capacity设置成Count。

 

TList的Notify                   

  最后,我想说的是Protected里的Notify。大家在Add的代码里面就能看到,在Insert、Delete之类的代码里我们也能看到Notify的踪迹。既然FList的内容已经被改变了,Notify还要做什么工作呢?看一下Notify的代码:

TListNotification = (InAdded, InExtracted, InDeleted);
procedure TList.Notify(Ptr: Pointer; Action: TListNotification);
begin

end;

  留着一个空的Notify有什么用呢?再看它的声明:

procedure Notify(Ptr: Pointer; Action: TListNotification);
virtual;

  原来Notify是一个虚函数,当我们因为有特殊要求而继承TList累的话,只要TList的内容一改变,我们就能得到通知。不过前提是我们要覆盖Notify这个procedure。

Delphi小谈之TList

标签:

原文地址:http://www.cnblogs.com/xumenger/p/4684680.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!