关于 Delphi 中记录的一些问题:
- 既然记录(records)几乎就像类(classes),为什么不仅使用类而不是记录呢?
- 从理论上讲,内存在变量声明时被分配给记录,但是内存是如何在之后释放的呢?
- 我可以理解将指针用于记录到列表对象中的实用性,但是通过泛型容器 (
TList<T>
),是否还需要使用指针?如果不需要,如何删除/释放泛型容器中的每个记录?如果我想要删除泛型容器中的特定记录,该怎么办?
记录与类之间有很多区别;并且没有"指向记录的指针" <> "类"。每种方式都有其优缺点;软件开发中重要的一点是了解这些差异,以便更轻松地选择最适合特定情况的方法。
对于问题1和2:记录是值类型,而类是引用类型。它们分配在堆栈上或直接在包含它们的任何较大变量的内存空间中,而不是通过指针,并且当它们超出范围时,编译器会自动清除它们。
至于第三个问题,TList<TMyRecord>
内部声明了一个 array of TMyRecord
以存储空间。当列表被销毁时,其中所有的记录都会被清除。如果您想删除特定的记录,请使用 Delete
方法按索引删除,或使用 Remove
方法查找并删除。但请注意,由于它是值类型,您所做的一切都将是复制记录,而不是复制对其的引用。
1) 为了实现继承和多态,类具有一些开销。记录不允许它们,并且在某些情况下可能更快且更简单易用。与始终分配在堆中并通过引用进行管理的类不同,记录也可以分配在栈上,直接访问,并互相赋值而无需调用“Assign”方法。此外,记录对于访问具有给定结构的内存块非常有用,因为它们的内存布局恰好是您定义的方式。类实例的内存布局由编译器控制,并具有使对象工作所需的附加数据(即指向虚拟方法表的指针)。
2) 除非您动态分配记录(使用New()或GetMem()),否则记录的内存由编译器作为序数、浮点数或静态数组来管理:全局变量内存在启动时分配并在程序终止时释放,而局部变量在进入函数/过程/方法时分配在堆栈上并在退出时释放。在堆栈上分配/释放内存更快,因为它不需要调用内存管理器,只需要很少的汇编指令来更改堆栈寄存器。但请注意,在堆栈上分配大型结构可能会导致堆栈溢出,因为最大堆栈大小是固定的且不是很大(请参见链接器选项)。如果记录是类的字段,则在创建类时分配它们,并在释放类时释放。
3) 泛型的优点之一是消除了低级指针管理的需要 - 但请注意其内部运作。
类和记录之间还有一些区别。 类可以使用多态,并公开接口。 记录不能实现析构函数(尽管自Delphi 2006以来,它们现在可以实现构造函数和方法)。
记录非常有用,可以将内存分段为更逻辑的结构,因为记录中第一个数据项位于指向记录本身的指针的相同地址点。 对于类来说,情况并非如此。