文档章节

学习 TList 类的实现[6]

涂孟超
 涂孟超
发布于 2014/09/26 15:33
字数 922
阅读 3
收藏 0
实现 TMyList.Add 函数.

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) then
    raise Exception.CreateFmt('非法的 Index:%d', [Index]);

  {删除的过程就是把当前元素后面的所有元素向前挪动一个位置}
  if Index < FCount then
    System.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);
var
  i: Integer;
begin
  {如果参数非法, 抛出异常}
  if (Value < 0) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);

  {如果预留内存不够, 马上申请}
  if Value > FCapacity then SetCapacity(Value);

  {如果参数大于元素总数没有赋值的用空字符填充}
  {如果参数小于元素总数, 删除多余的元素      }
  if Value > FCount then
    FillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)
  else
    for i := FCount - 1 downto Value do
      Delete(I);

  {新的元素总数}
  FCount := Value;
end;

 
 
 
 
 

 

 

  
还有一个 TMyList.Clear 方法.

因为不用考虑列表中对象释放的问题, 这个就简单多了.
procedure TMyList.Clear;
begin
  SetCount(0);
  SetCapacity(0);
end;

 
 
 
 
 

 

 

  
至此, 已经声明的方法都实现了, 这个 TMyList 类也该能凑合使用了.

源码如下:
unit MyList;

interface

uses SysUtils;

const
  MaxListSize = Maxint div 16;

type
  PPointerList = ^TPointerList;
  TPointerList = array[0..MaxListSize - 1] of Pointer;

  TMyList = class(TObject)
  private
    FList: PPointerList;
    FCount: Integer;
    FCapacity: Integer;
    procedure SetCapacity(const Value: Integer);
    procedure SetCount(const Value: Integer);
  public
    destructor 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;
begin
  if FCount = FCapacity then SetCapacity(FCapacity + 4);
  FList^[FCount] := Item;
  Result := FCount;
  Inc(FCount);
end;

procedure TMyList.Clear;
begin
  SetCount(0);
  SetCapacity(0);
end;

procedure TMyList.Delete(Index: Integer);
begin
  if (Index < 0) or (Index >= FCount) then
    raise Exception.CreateFmt('非法的 Index:%d', [Index]);

  if Index < FCount then
    System.Move(FList^[Index+1], FList^[Index], (FCount-Index)* SizeOf(Pointer));

  Dec(FCount);
end;

destructor TMyList.Destroy;
begin
  Clear;
  inherited;
end;

procedure TMyList.SetCapacity(const Value: Integer);
begin
  if (Value < FCount) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);

  if FCapacity <> Value then
  begin
    ReallocMem(FList, Value * SizeOf(Pointer));
    FCapacity := Value;
  end;
end;

procedure TMyList.SetCount(const Value: Integer);
var
  i: Integer;
begin
  if (Value < 0) or (Value > MaxListSize) then
    raise Exception.CreateFmt('非法数据:%d', [Value]);

  if Value > FCapacity then SetCapacity(Value);

  if Value > FCount then
    FillChar(FList^[FCount], (Value - FCount) * SizeOf(Pointer), 0)
  else
    for i := FCount - 1 downto Value do
      Delete(I);

  FCount := Value;
end;

end.

 
 
 
 
 

 

 

  

本文转载自:http://www.cnblogs.com/del/archive/2008/03/28/1127803.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
windows环境中vim插件配置(便利的vim)

打开vim的文件类型自动检测功能:filetype on,就是在vimrc文件中加上filetype on 1.ctags 1.1ctags功能: tags是个exe文件,在shell中执行来在工程目录中创建tags(就是函数的映射关系),适...

_FreeDoM
2014/06/04
0
0
vim for php IDE 我的打造过程

vim是一个很强的神器,对于我只用到其中的一小部分内容,接下来是我打造 php IDE的全过程,希望有兄弟能指点我其中的不足,要学习的兄弟能跟我一起努力学习。 第一步:配_vimrc,配成自己喜欢...

路边拾草人
2011/04/16
10.2K
21
VIM编辑器支持Python开发环境(Vim+Ctags+Taglist)

在Linux下用VI编辑器进行Python开发,有必要对VI编辑器进行一些配置,使其具备以下特性: 1、加强的 Python 语法高亮显示; 2、对脚本、项目生成 ctag 序列; 3、在 vim 中显示 ctag 序列列表...

庄小寒
2014/02/26
0
0
强大的vim配置,让编程更随意

转自:http://blog.csdn.net/chary8088/article/details/7715383 花了很长时间整理的,感觉用起来很方便,共享一下。 我的vim配置主要有以下优点: 1.按F5可以直接编译并执行C、C++、java代码...

长平狐
2013/01/11
221
0
FastJSON配合Redis存取处理map数据

伪代码如下:

Alexdevlin
2017/07/26
12
0

没有更多内容

加载失败,请刷新页面

加载更多

jenkins安装

https://my.oschina.net/u/593517/blog/1797968 jenkins 安装 https://my.oschina.net/u/593517/blog/3028175 GIT 安装 https://my.oschina.net/u/593517/blog/3028179 maven 安装 插件安装 ......

Gm_ning
16分钟前
1
0
小言服务端解决方案-监控

框架保证方向,整体包容细节 为保证服务端运行平稳正常,owner应使得系统应保有相应的监控:系统监控,业务监控。而服务运行的平稳高效是否有保障跟监控粒度又成直接的正比关系。本文仅针对开...

重城重楼
28分钟前
0
0
搜索引擎(Elasticsearch搜索详解)

学完本课题,你应达成如下目标: 掌握ES搜索API的规则、用法。 掌握各种查询用法 搜索API 搜索API 端点地址 GET /twitter/_search?q=user:kimchy GET /twitter/tweet,user/_search?q=user:...

这很耳东先生
51分钟前
7
0
浅谈如何减少GC的次数

GC会stop the world。会暂停程序的执行,带来延迟的代价。所以在开发中,我们不希望GC的次数过多。 本文将讨论如何在开发中改善各种细节,从而减少GC的次数。 (1)对象不用时最好显式置为 Nu...

浮躁的码农
53分钟前
1
0
jpa 自定义返回对象

任何ORM框架都少不了开放自定义sql的问题。jpa自然也不例外,很多场景需要写复杂sql的。 首先定义一个方法签名,然后打上@Query注解。像下面这样,需要注意nativeQuery,这个表示query中的字...

朝如青丝暮成雪
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部