在Delphi中使用动态记录数组与TList<TMyRecord>有什么优缺点?

7
这是一个理论问题,旨在生成Delphi中不同数据存储方式的优缺点查找列表。
假设我们有一条记录:
type
  TMyRecord = record 
    X,Y,Z: Single; 
    IsValid: Boolean; 
  end;

存储这样记录的基本选项如下:

  • TMyRecord数组;
  • 具有getter/setter的自定义TList的后代;
  • TList<TMyRecord>;

我特别关心#1和#3之间的比较,它们之间的差异有多大,尤其是在性能方面。


#2和#3本质上是相同的,模板可以为您进行自定义。使用数组,您可以将记录连续存储。 - Free Consulting
1
实际上不是这样。TList<T> 操作的是值而不是指针(与 TList 不同)。 - Fr0sT
2个回答

12

TList<T> 优点:

  • Array没有有用的方法进行添加/插入/删除/排序/搜索,而TList具备这些功能。
  • TList具有Notify方法,可以被覆盖以在添加/删除项目时执行某些自定义操作。

TList<T> 缺点:

  • TList<T>[i]实际上返回其元素的副本。因此,您不能编写像TList<TMyRec>[idx].SomeField := foo这样的语句。相反,您必须使用临时变量。数组显然允许这样的表达式。 David Heffernan提到了TList<T>.List,它消除了这个缺点;但是,它只出现在XE3中
  • TList是一个对象,在不需要时应该在程序完成时删除.
  • System.Generics.Collections单元可能会给之前未使用System.Classes单元的项目增加很多二进制大小。

我为自己编写了TRecordList<T>类,它将项目作为指针(就像经典TList一样)进行操作。


2
TList<T>.List 是动态数组,所以不需要复制。在性能方面,动态数组没有优劣之分。 - David Heffernan
你的 TRecordList<T> 对缓存不是有影响吗? - David Heffernan
1
“在程序结束时删除”…实际上应该在超出作用域或不再使用时删除/释放。 - jpfollenius
事实上,如果你等到程序结束才释放它,那么基本上没有什么意义,因为系统会自动回收它。 - David Heffernan
@David Heffernan:感谢您提到TList<T>.List,它仅在XE3中添加,而我仍在使用XE2。@jpfollenius,您肯定是对的。@David Heffernan:也许这对于缓存来说不好,但对于项目插入/排序等操作来说是好的。 - Fr0sT
@Fr0sT 是的,这有点取决于使用场景。指针列表在某些情况下可能是有效的。我想我当时想象的是线性访问模式。 - David Heffernan

7

tl;dr

  • 指向独立内存块的指针列表对缓存不友好,应该避免使用。
  • 动态数组与TList<T>具有相同的性能特征。
  • TList<T>提供了许多方便程序员的功能,而动态数组则没有。

TList<T>的实现是将项存储在动态数组中。因此,TList<T>TArray<T>之间基本上没有性能差异。

当然,动态数组可以直接访问元素而无需进行复制。如果这很重要,您也可以使用TList<T>List属性来完成相同的操作。实际上,这个属性意味着在性能方面,至少TList<T>与普通动态数组相匹配。

除了性能外,使用TList<T>还可以带给你各种便利,而原始动态数组则没有。我不需要列举这些便利。从公开方法和属性列表中,您可以清晰地看到它们。

由于性能对您很重要,因此您应该解决问题中的真正性能问题。也就是说,您压缩了您的记录。这将导致大多数记录实例被错误对齐。而这对性能有严重的影响。如果您关心性能,您将对齐结构。

您的第二个选项,指针列表,不值得考虑。它可能会在地址空间中分散内存,并且对缓存不友好。


1
当我在第一行提到这是理论问题或不是我的代码(上次你暗示了)时 - 我的意思就是这样。代码片段只是一个例子。我不知道你从哪里读到我有性能问题%) - Kromster
@Krom 在你修改问题之前,我回答的问题有一个打包记录。这些由于错位而具有可怕的性能问题。如果我忽视它,那将是极其疏忽的。这不仅因为你比较的两个东西的性能完全相同,因为它们基本上只是数组。对于它们来说,性能不能真正得到提高。我回答的问题唯一的性能问题就是紧凑的数组。如果存在错位,那么错位将是一个重大问题。 - David Heffernan
你可以自行判断是否存在对齐问题。在代码库中搜索 packed。 - David Heffernan
“packed”值得一提,我感谢您的评论。然而,我的主要问题是关于使用和性能差异的,#1-#3给出了其他所有内容相同(是否压缩)。谢谢。 - Kromster
好的,我已经回答过了。性能上没有任何区别。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接