zoukankan      html  css  js  c++  java
  • TList

    Tlist (Classes.pas)

    在我刚开始接触TList的时候,TList搞得我迷雾重重,都是Capacity属性惹的祸。我查了Delphi的帮助,它说Capacity是TList的最大容量,又在什么地方说MaxIntdiv 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, lnAdded);

    { 给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
    if FCapacity > 8 then
    Delta := 16
    else
    Delta := 4;

    { 改变数组大小 }
    SetCapacity(FCapacity + Delta);
    end;

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

    TList 除了保存的对象是指针以外,其它地方都与TstringList很像。所以接下来我只介绍二者不同之处。

    我们同样可以使用TList或者TList.Items获得某一位置的指针。如果嫌TList.Items是属性没有效率的话,这里还有一个List属性,指向内部的FList,可以这么用:

    TList.List^。

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

    TList 也提供了一个Remove方法。与Delete不同的是,Delete删除的是已知位置的指针,Remove删除的是已知指针。只要TList 包含有你想删除的指针,就可以使用Remove(Pointer)。Remove的返回值是指针在还没有被删除之前的位置。使用方法如下:

    procedure Delete(Index: Integer);

    function Remove(Item: Pointer): Integer;

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

    最后,我想说的是Protected里的Notify。大家在Add的代码里就能看到,在Insert、Delete之类的代码里我们也能看得到Notify的踪迹。既然FList的内容已经被改变了,Notify 还要做什么工作呢?看一下Notify的代码:学习笔记
    TListNotification = (lnAdded, lnExtracted, lnDeleted);
    procedure TList.Notify(Ptr: Pointer; Action:
    TListNotification);
    begin
    end;
    留着一个空的Notify 有什么用呢?再看它的声明:
    procedure Notify(Ptr: Pointer; Action: TListNotification);
    virtual;
    原来Notify 是一个虚函数,当我们因为有特殊要求而继承TList类的话,只要TList 的内容一改变,我们就能得到通知。不过前提是我们要覆盖N o t i f y 这个
    Procedure。

  • 相关阅读:
    使用 Sublime、WebStorm 开发 Jade
    3-微信小程序开发(小程序的目录结构说明)
    1-微信小程序开发(安装软件和运行第一个微信小程序)
    29-ESP8266 SDK开发基础入门篇--编写TCP 客户端程序(Lwip RAW模式,非RTOS版,精简入门)
    28-ESP8266 SDK开发基础入门篇--编写wifi模块TCP 客户端程序(官方API版,非RTOS版)
    27-ESP8266 SDK开发基础入门篇--编写Android SmartConfig一键配网程序
    26-ESP8266 SDK开发基础入门篇--编写WIFI模块 SmartConfig/Airkiss 一键配网
    25-ESP8266 SDK开发基础入门篇--控制WIFI连接路由器
    17-网页,网站,微信公众号基础入门(使用Adobe Dreamweaver CS6 制作网页/网站)
    15-网页,网站,微信公众号基础入门(网页版MQTT,做自己的MQTT调试助手)
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2940671.html
Copyright © 2011-2022 走看看