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