德尔福记录

发布于 2024-08-15 02:42:15 字数 243 浏览 1 评论 0原文

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

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

some questions about records in Delphi:

  1. As records are almost like classes, why not use only classes instead of records?
  2. In theory, memory is allocated for a record when it is declared by a variable; but, and how is memory released after?
  3. I can understand the utility of pointers to records into a list object, but with Generics Containers (TList<T>), are there need to use pointer yet? if not, how to delete/release each record into a Generic Container? If I wanna delete a specific record into a Generic Container, how to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

故事灯 2024-08-22 02:42:16

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

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

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

One of the main benefits of records is, when you have a large "array of record". This is created in memory by allocating space for all records in one contiguous RAM space, which is extremely fast. If you had used "array of TClass" instead, each object in the array would have to be allocated by itself, which is slow.

There has been a lot of work to improve the speed of allocating memory, in order to improve the speed of strings and objects, but it will never be as fast as replacing 100,000 memory allocations with 1 memory allocation.

However, if you use array of record, don't copy the record around in local variables. That may easily kill the speed benefit.

没︽人懂的悲伤 2024-08-22 02:42:16

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

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

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

1) To allow for inheritance and polymorphism, classes have some overhead. Records do not allow them, and in some situations may be somewhat faster and simpler to use. Unlike classes, that are always allocated in the heap and managed through references, records can be allocated on the stack also, accessed directly, and assigned each other without requiring to call an "Assign" method.
Also records are useful to access memory blocks with a given structure, because their memory layout is exactly how you define it. A class instance memory layout is controlled by the compiler and has additional data to make objects work (i.e. the pointer to the Virtual Method Table).

2) Unless you allocate records dynamically, using New() or GetMem(), record's memory is managed by the compiler as ordinals, floats or static arrays: global variables memory is allocated at startup and released when the program terminates, and local variables are allocated on the stack entering a function/procedure/method and released exiting. Allocating/releasing memory in the stack is faster because it doesn't require calls to the memory manager, it's just very few assembler instructions to change the stack registers. But be aware that allocating large structure on the stack may cause a stack overflow, because the maximum stack size is fixed and not very large (see linker options).
If records are fields of a class, they are allocated when the class is created and released when the class is freed.

3) One of the advantages of generics is to eliminate the need of low-level pointer management - but be aware of the inner workings.

硬不硬你别怂 2024-08-22 02:42:16

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

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

There are a few other differences between a class and a record. Classes can use polymorphism, and expose interfaces. Records can not implement destructors (although since Delphi 2006 they can now implement constructors and methods).

Records are very useful in segmenting memory into a more logical structure since the first data item in the record is at the same address point of the pointer to the record itself. This is not the case for classes.

赠意 2024-08-22 02:42:15

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

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

  4. 指向记录的指针是否像类一样?不,一点也不。只有两个区别:
    • 类支持多态继承。
    • 类可以实现接口。

There are lots of differences between records and classes; and no "Pointer to record" <> "Class". Each has its own pros and cons; one of the important things about software development is to understand these so you can more easily choose the most appropriate for a given situation.

  1. This question is based on a false premise. Records are not almost like classes, in the same way that Integers are not almost like Doubles.
    • Classes must always be dynamically instantiated, whereas this is a possibility, but not a requirement for records.
    • Instances of classes (which we call objects) are always passed around by reference, meaning that multiple sections of code will share and act on the same instance. This is something important to remember, because you may unintentionally modify an object as a side-effect; although when done intentionally it's a powerful feature. Records on the other hand are passed by value; you need to explicitly indicate if you're passing them by reference.
    • Classes do not 'copy as easily as records'. When I say copy, I mean a separate instance duplicating a source. (This should be obvious in light of the value/reference comment above).
    • Records tend to work very nicely with typed files (because they're so easy to copy).
    • Records can overlay fields with other fields (case x of/unions)
    • These were comments on certain situational benefits of records; conversely, there are also situational benefits for classes that I'll not elaborate on.
  2. Perhaps the easiest way to understand this is to be a little pedantic about it. Let's clarify; memory is not really allocated 'when its declared', it's allocated when the variable is in scope, and deallocated when it goes out of scope. So for a local variable, it's allocated just before the start of the routine, and deallocated just after the end. For a class field, it's allocated when the object is created, and deallocated when it's destroyed.
  3. Again, there are pros and cons...
    • It can be slower and require more memory to copy entire records (as with generics) than to just copy the references.
    • Passing records around by reference (using pointers) is a powerful technique whereby you can easily have something else modify your copy of the record. Without this, you'd have to pass your record by value (i.e. copy it) receive the changed record as a result, copy it again to your own structures.
  4. Are pointers to records like classes? No, not at all. Just two of the differences:
    • Classes support polymorphic inheritance.
    • Classes can implement interfaces.
满身野味 2024-08-22 02:42:15

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

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

For 1 and 2: records are value types, while classes are reference types. They're allocated on the stack, or directly in the memory space of any larger variable that contains them, instead of through a pointer, and automatically cleaned up by the compiler when they go out of scope.

As for your third question, a TList<TMyRecord> internally declares an array of TMyRecord for storage space. All the records in it will be cleaned up when the list is destroyed. If you want to delete a specific one, use the Delete method to delete by index, or the Remove method to find and delete. But be aware that since it's a value type, everything you do will be making copies of the record, not copying references to it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文