德尔福记录
关于Delphi中记录的一些问题:
- 由于记录几乎就像类,为什么不只使用类而不使用记录?
- 理论上,当变量声明记录时,就会为记录分配内存;但是,之后内存是如何释放的呢?
- 我可以理解指向列表对象中的记录的指针的实用性,但是对于泛型容器(
TList
),是否还需要使用指针?如果没有,如何删除/释放每条记录到通用容器中?如果我想删除通用容器中的特定记录,该怎么做?
some questions about records in Delphi:
- As records are almost like classes, why not use only classes instead of records?
- In theory, memory is allocated for a record when it is declared by a variable; but, and how is memory released after?
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
记录的主要好处之一是,当您拥有大量“记录数组”时。这是通过在一个连续的 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.
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.
类和记录之间还有一些其他区别。类可以使用多态性,并公开接口。记录无法实现析构函数(尽管自 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.
记录和类别之间存在很多差异;并且没有“记录指针”<>“类”。每个都有自己的优点和缺点;软件开发的重要事项之一是了解这些,以便您可以更轻松地选择最适合特定情况的软件。
复制整个记录(与泛型一样)比
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 和 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 anarray 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 theDelete
method to delete by index, or theRemove
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.