学习 TList 类的实现[6]
TList 中的 Add 函数用到了一个 Grow 方法, 它的原理是元素越多就为以后准备更多内存, 我们这里省略为预留 4 个元素的内存;
TList 中的 Add 函数还同时触动了一个 Notify 方法, 这应该是为它们的子类准备的(估计是用它来激发一个事件的), 也不要了.
function TMyList.Add(Item: Pointer): Integer; begin{如果预申请的内存用完了, 再申请够 4 个元素用的}if FCount = FCapacity then SetCapacity(FCapacity + 4);{Add 是添加在最后面, 把指针赋予数组}FList^[FCount] := Item;{函数返回}Result := FCount;{元素总数 + 1}Inc(FCount); end;
再实现 TMyList.Delete 过程.
同前, 把错误处理也简化成一个异常; 也省略了对 Notify 方法的触动.
其中用到了 System.Move, 可以参考: http://www.cnblogs.com/del/archive/2008/03/27/1126226.html
这里有一个问题是需要高度注意的: TList 在删除一个元素(它的元素就是指针)时, 并没有释放指针指向的对象, 只是从列表开除;
如果要同时 Free 掉对象, 应该使用 Contnrs 单元下的 TObjectList 类.
procedure TMyList.Delete(Index: Integer); begin{如果给的 Index 不符合要求, 就抛出异常}if (Index < 0) or (Index >= FCount) thenraise Exception.CreateFmt('非法的 Index:%d', [Index]);{删除的过程就是把当前元素后面的所有元素向前挪动一个位置}if Index < FCount thenSystem.Move(FList^[Index + 1], FList^[Index], (FCount - Index) * SizeOf(Pointer));{总数 - 1}Dec(FCount); end;
还要实现 TMyList.SetCount 方法.
之前我没有想到 Count 属性还是可写的; 这可够狠的, 譬如已经有 100 个元素, 如果让 Count := 1; 这一下就要删除后面 99 个元素!
还有不理解的是: 譬如已经有 100 个元素, 如果让 Count := 200; 那后面的 100 个元素即便是填充了空字符, 用指针读过来也不是对象啊? 觉得不妥. 不过暂时也这样了.
procedure TMyList.SetCount(const Value: Integer); vari: Integer; begin{如果参数非法, 抛出异常}if (Value < 0) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);{如果预留内存不够, 马上申请}if Value > FCapacity then SetCapacity(Value);{如果参数大于元素总数没有赋值的用空字符填充}{如果参数小于元素总数, 删除多余的元素 }if Value > FCount thenFillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)elsefor i := FCount - 1 downto Value doDelete(I);{新的元素总数}FCount := Value; end;
还有一个 TMyList.Clear 方法.
因为不用考虑列表中对象释放的问题, 这个就简单多了.
procedure TMyList.Clear; beginSetCount(0);SetCapacity(0); end;
至此, 已经声明的方法都实现了, 这个 TMyList 类也该能凑合使用了.
源码如下:
unit MyList;interfaceuses SysUtils;constMaxListSize = Maxint div 16;typePPointerList = ^TPointerList;TPointerList = array[0..MaxListSize - 1] of Pointer;TMyList = class(TObject)privateFList: PPointerList;FCount: Integer;FCapacity: Integer;procedure SetCapacity(const Value: Integer);procedure SetCount(const Value: Integer);publicdestructor Destroy; override;function Add(Item: Pointer): Integer;procedure Clear;procedure Delete(Index: Integer);property Capacity: Integer read FCapacity write SetCapacity;property Count: Integer read FCount write SetCount;property List: PPointerList read FList;end;implementation{ TMyList }function TMyList.Add(Item: Pointer): Integer; beginif FCount = FCapacity then SetCapacity(FCapacity + 4);FList^[FCount] := Item;Result := FCount;Inc(FCount); end;procedure TMyList.Clear; beginSetCount(0);SetCapacity(0); end;procedure TMyList.Delete(Index: Integer); beginif (Index < 0) or (Index >= FCount) thenraise Exception.CreateFmt('非法的 Index:%d', [Index]);if Index < FCount thenSystem.Move(FList^[Index+1], FList^[Index], (FCount-Index)* SizeOf(Pointer));Dec(FCount); end;destructor TMyList.Destroy; beginClear;inherited; end;procedure TMyList.SetCapacity(const Value: Integer); beginif (Value < FCount) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);if FCapacity <> Value thenbeginReallocMem(FList, Value * SizeOf(Pointer));FCapacity := Value;end; end;procedure TMyList.SetCount(const Value: Integer); vari: Integer; beginif (Value < 0) or (Value > MaxListSize) thenraise Exception.CreateFmt('非法数据:%d', [Value]);if Value > FCapacity then SetCapacity(Value);if Value > FCount thenFillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)elsefor i := FCount - 1 downto Value doDelete(I);FCount := Value; end;end.
转载于:https://www.cnblogs.com/shijiaoyun/p/3844510.html
学习 TList 类的实现[6]相关推荐
- 学习 TList 类的实现[5]
先来实现 TMyList.SetCapacity. 马上会想到下面代码: procedure TMyList.SetCapacity(const Value: Integer); beginif FC ...
- 如何学习streamdecoder类_如何学习篇5:强化2种能力——2种学习模式之运动类:隐性学习...
[本文摘要] [注]本文所述内容为学习Yjango<学习观>相关视频之后的总结,观点归Yjango所有,本文仅作为学习之用. 阅读本节,会让你对英语这类运动类知识的学习豁然开朗,你会知道英 ...
- java中蛇的属性有哪些_学习Java类的属性
学习Java类的属性-武汉北大青鸟 Public.private.protected显示了三种类中的属性和服务的类型,public是可以随意访问的.private是外界不能访问的(显示了数据的封装性) ...
- 普通话测试软件测分准吗,普通话学习测试类 | 普通话测试APP,能做到测试、学习提高两不误吗?...
原标题:普通话学习测试类 | 普通话测试APP,能做到测试.学习提高两不误吗? 普通话是如今人们生活的常用语言,但要说到参加普通话测试,如果没有提前了解普通话测试的形式与要求,也不知道自己普通话的起步 ...
- 学信息安全买计算机,大学学习计算机类信息安全方向真的很蠢吗?
大学学习计算机类信息安全方向真的很蠢吗? 本人2018届高考党,目前水平可以上一个不错的211,望借自主招生冲击985院校. 几天前,当我对老师说:"我目前最优先的选择是计算机-信息安全方向 ...
- java虚拟机预先加载哪些类_Java虚拟机JVM学习02 类的加载概述
Java虚拟机JVM学习02 类的加载概述 类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对 ...
- Java为枚举类创建成员变量_Java学习——枚举类
Java学习--枚举类 摘要:本文主要介绍了Java的枚举类. 部分内容来自以下博客: https://www.cnblogs.com/sister/p/4700702.html https://bl ...
- 2020-用多通道卷积神经网络学习单类特征用于人脸表现攻击检测
2020年,Anjith George等人,期刊:TIFS,CCFA刊,Learning One Class Representations for Face Presentation Attack ...
- 游戏策划学习:类银河恶魔城、烬
游戏策划学习:类银河恶魔城.烬 1.roguelike和银河恶魔城类游戏的区别 (1).地图复用是银河恶魔城类非常重要的一个特征.通过剧情导向和收集要素,让玩家多次探索同一个地图区域,用有限的资源延长 ...
最新文章
- 递推DP UVA 1366 Martian Mining
- [leetcode] Pow(x, n)
- Android被逼学习例子2
- 常见多媒体文件格式及视音频编解码总结
- qt编译器5.12.3怎么一次性删除所有的断点
- emmet插件使用(Css)
- SSIS Dataflow使用存储过程不能检索列名
- 论文解读丨基于局部特征保留的图卷积神经网络架构(LPD-GCN)
- Vmware和Citrix各自发展史
- Head First 设计模式 —— 工厂模式与工厂方法
- eclipse导入wsdl文件_Eclipse+Axis使用WSDL文件生成Web Service服务端/客户端
- Ubuntu 安装Chromium浏览器
- PLM与ERP的区别
- 客户端到服务器端的通信过程及 原理图很好
- 吴恩达深度学习02-3.567 Batch Normalization(BN)
- 李飞飞在谷歌开发者大会宣布谷歌AI中国中心正式成立
- 关于解决win10重装后右键单击一直转圈的问题
- Treap + FHQ Treap
- php 获取文件夹下面的文件列表和文件夹列表
- ABAP WB01 BDC ”No batch input data for screen “ ”没有屏幕 的批输入数据“
热门文章
- js动态添加的元素,动作绑定
- 目标检测(Object Detection)综述--R-CNN/Fast R-CNN/Faster R-CNN/YOLO/SSD
- TimingWheel[时间轮]介绍
- (05)VHDL实现分频器
- 1006.arm 板中杀死进程
- python制作一个简单的udp聊天器
- .net 反编译_向.net/Unity 程序员推荐一个十分因吹斯听的网站:sharplab.io
- vector容器动态申请内存的过程_记录一次自定义Allocator profile的过程
- Linux基本命令介绍
- nginx基础概念(100%)之connection