关于Delphi中记录的一些问题:

  1. 由于记录几乎就像类,为什么不只使用类而不使用记录呢?
  2. 理论上,当变量声明记录时,就会为记录分配内存;但是,之后内存是如何释放的呢?
  3. 我可以理解指向列表对象中的记录的指针的实用性,但是使用泛型容器(TList<T>),还需要使用指针吗?如果没有,如何删除/释放每条记录到通用容器中?如果我想删除通用容器中的特定记录,该怎么做?
有帮助吗?

解决方案

对于 1 和 2:记录是值类型,而类是引用类型。它们在堆栈上分配,或者直接在包含它们的任何较大变量的内存空间中分配,而不是通过指针,并且当它们超出范围时由编译器自动清理。

至于你的第三个问题, TList<TMyRecord> 内部声明了一个 array of TMyRecord 用于存储空间。当列表被销毁时,其中的所有记录都会被清除。如果您想删除特定的一个,请使用 Delete 通过索引删除的方法,或者 Remove 方法查找并删除。但请注意,由于它是值类型,因此您所做的一切都将复制记录,而不是复制对其的引用。

其他提示

记录和类别之间存在很多差异;并且没有“记录指针” <> “班级”。每个都有自己的优点和缺点;软件开发的重要事项之一是了解这些,以便您可以更轻松地选择最适合特定情况的软件。

  1. 这个问题是基于一个错误的前提。记录与类不同,就像整数与双精度数不同一样。
    • 类必须始终动态实例化,虽然这是一种可能性,但不是记录的要求。
    • 类的实例(我们称之为对象)始终通过引用传递,这意味着多个代码段将共享并作用于同一个实例。记住这一点很重要,因为您可能会无意中修改对象作为副作用;尽管如果有意这样做的话,它是一个强大的功能。另一方面,记录是按值传递的;您需要明确指出是否通过引用传递它们。
    • 类并不“像记录那样容易复制”。当我说复制时,我指的是复制源的单独实例。(根据上面的价值/参考评论,这应该是显而易见的)。
    • 记录往往与键入的文件配合得很好(因为它们很容易复制)。
    • 记录可以将字段与其他字段重叠(case x of/unions)
    • 这些是对记录的某些情境效益的评论;相反,课程也有情境优势,我不会详细说明。
  2. 也许理解这一点最简单的方法就是稍微迂腐一些。让我们澄清一下;内存并不是在“声明时”真正分配的,而是在变量处于作用域内时分配的,并在变量超出作用域时释放的。因此,对于局部变量,它在例程开始之前分配,并在结束之后释放。对于类字段,它在创建对象时分配,并在对象销毁时释放。
  3. 再说一遍,有利有弊……
    • 与仅复制引用相比,复制整个记录(与泛型一样)可能会更慢并且需要更多内存。
    • 通过引用(使用指针)传递记录是一种强大的技术,您可以轻松地让其他东西修改您的记录副本。如果没有这个,你就必须按值传递你的记录(即复制它)接收更改的记录作为结果,再次将其复制到您自己的结构中。
  4. 指向记录的指针是否像类一样?一点都不。只有两个区别:
    • 类支持多态继承。
    • 类可以实现接口。

记录的主要好处之一是,当您拥有大量“记录数组”时。这是通过在一个连续的 RAM 空间中为所有记录分配空间来在内存中创建的,速度非常快。如果您使用“TClass 数组”,则数组中的每个对象都必须自行分配,这很慢。

为了提高字符串和对象的速度,已经做了很多工作来提高分配内存的速度,但永远不会像用 1 次内存分配代替 100,000 次内存分配那么快。

但是,如果您使用记录数组,请勿在局部变量中复制记录。这可能很容易扼杀速度优势。

类和记录之间还有一些其他区别。类可以使用 多态性, ,并公开接口。记录无法实现析构函数(尽管自 Delphi 2006 以来它们现在可以实现构造函数和方法)。

记录对于将内存分段为更逻辑的结构非常有用,因为记录中的第一个数据项与指向记录本身的指针位于同一地址点。类的情况并非如此。

1)为了允许继承和多态性,类有一些开销。记录不允许使用它们,并且在某些情况下可能会更快且更简单地使用。与总是在堆中分配并通过引用管理的类不同,记录也可以在堆栈上分配、直接访问并相互分配,而无需调用“Assign”方法。此外,记录对于访问具有给定结构的内存块很有用,因为它们的内存布局正是您定义的方式。类实例内存布局由编译器控制,并具有使对象工作的附加数据(即指向虚拟方法表的指针)。

2) 除非您使用 New() 或 GetMem() 动态分配记录,否则记录的内存由编译器作为序号、浮点数或静态数组进行管理:全局变量内存在启动时分配并在程序终止时释放,局部变量在进入函数/过程/方法时在堆栈上分配并在退出时释放。在堆栈中分配/释放内存速度更快,因为它不需要调用内存管理器,只需很少的汇编指令即可更改堆栈寄存器。但请注意,在堆栈上分配大型结构可能会导致堆栈溢出,因为最大堆栈大小是固定的并且不是很大(请参阅链接器选项)。如果记录是类的字段,则它们在创建类时分配,并在类释放时释放。

3) 泛型的优点之一是消除低级指针管理的需要 - 但要注意内部工作原理。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top