2009-12-09 77 views
14

有关记录德尔福一些问题:记录在Delphi

  1. 作为记录几乎像班,为什么不使用只类的,而不是记录?
  2. 理论上讲,当内存被一个变量声明时,它被分配给一条记录;但是,以及内存如何发布后?
  3. 我可以理解指针的记录到列表对象的实用程序,但与泛型容器(TList<T>),是否需要使用指针呢?如果没有,如何删除/释放每个记录到一个通用容器?如果我想删除一个特定的记录到一个通用容器中,该怎么做?

回答

10

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

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

+0

谢谢惠勒先生,还有一个问题更多: 指向record = Class? – 2009-12-09 21:49:28

+1

不,指向记录的指针=指向记录的指针。一个对象(类实例)以多种方式与记录不同。 – 2009-12-09 23:05:50

3

类和记录之间还有一些其他的区别。类可以使用polymorphism,并公开接口。记录不能实现析构函数(尽管从Delphi 2006开始,它们现在可以实现构造函数和方法)。

由于记录中的第一个数据项与指向记录本身的指针的相同地址点,记录在将内存分割成更为逻辑的结构中非常有用。这不是类的情况。

+0

另外,记录支持操作符重载,在某些情况下可能会有用。 – 2009-12-16 00:47:49

19

记录和类之间有很多不同之处;并且没有“记录指针”<>“Class”。每个人都有自己的优点和缺点;关于软件开发的重要事情之一是理解这些,以便您可以更轻松地选择最适合于给定情况的选项。

  1. 这个问题是基于一个错误的前提。记录几乎不像类,就像整数几乎不像双精度一样。
    • 类必须始终动态实例化,而这是一种可能性,但不是记录的要求。
    • 类的实例(我们称之为对象)总是通过引用传递,这意味着多段代码将共享并在同一个实例上执行。这是要记住的重要事情,因为您可能会无意中将对象修改为副作用;虽然故意完成这是一个强大的功能。另一方面,记录按价值传递;您需要明确指出是否通过引用传递它们。
    • 班级不像记录那么容易复制。当我说复制时,我的意思是复制源的单独实例。 (根据上面的价值/参考评论,这应该是显而易见的)。
    • 记录通常与输入文件非常吻合(因为它们非常容易复制)。
    • 记录可以与其他字段叠加(字段x /工会)
    • 这些是对记录的某些情境益处的评论;相反,对于我不会详细阐述的课程来说,情境益处也是如此。
  2. 也许最简单的方法来理解这是对它有点迂回。让我们澄清一下;内存在其声明时并不真正分配,当变量处于范围内时分配内存,当内存超出范围时释放内存。所以对于一个局部变量,它就在例程开始之前分配,并在结束后立即释放。对于类字段,它在创建对象时分配,并在销毁时释放。
  3. 同样,也有优点和缺点...
    • 它可以是慢,需要比仅复制引用更多的内存来复制整个记录(如仿制药)。
    • 通过引用传递记录(使用指针)是一种功能强大的技术,您可以轻松地让其他内容修改记录副本。如果没有这个,你必须通过价值传递你的记录(即复制它)接收更改后的记录,并将它复制到你自己的结构中。
  4. 是类指针的记录指针?一点都不。只有两个区别:
    • 类支持多态继承。
    • 类可以实现接口。
+0

感谢Marco提供有关变体记录的注释(使用...的情况x) – 2009-12-10 09:18:37

9

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

为了提高字符串和对象的速度,提高内存分配的速度已经有很多工作要做,但它决不会像用1个内存分配替换100,000个内存分配一样快。

但是,如果您使用记录数组,请不要在本地变量中复制记录。这可能很容易杀死速度优势。

3

1)为了允许继承和多态,类有一些开销。记录不允许它们,并且在某些情况下可能会更快,更简单。与类不同,类总是分配在堆中并通过引用进行管理,记录也可以分配到堆栈中,直接访问并相互分配,而无需调用“分配”方法。 另外,记录对于访问具有给定结构的内存块很有用,因为它们的内存布局正是您如何定义它的。类实例内存布局由编译器控制,并具有用于使对象工作的附加数据(即指向虚拟方法表的指针)。 2)除非使用New()或GetMem()动态分配记录,否则记录的内存由编译器按照序数,浮点数或静态数组的形式进行管理:全局变量内存在启动时分配并在程序终止时释放,并且局部变量在堆栈中被分配进入一个函数/过程/方法并且被释放退出。在堆栈中分配/释放内存的速度更快,因为它不需要调用内存管理器,只需要很少的汇编指令即可更改堆栈寄存器。但请注意,在堆栈上分配大型结构可能会导致堆栈溢出,因为最大堆栈大小是固定的并不是很大(请参阅链接器选项)。 如果记录是类的字段,则在类被释放时创建并释放它们时分配它们。

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

相关问题