【发布时间】:2010-10-22 00:12:24
【问题描述】:
在 C++ 等其他语言中,您必须自己跟踪数组长度 - Delphi 如何知道我的数组长度?是否有一个内部的隐藏整数?
对于性能关键部分,不使用 Length() 而是使用我管理的直接整数会更好吗?
【问题讨论】:
在 C++ 等其他语言中,您必须自己跟踪数组长度 - Delphi 如何知道我的数组长度?是否有一个内部的隐藏整数?
对于性能关键部分,不使用 Length() 而是使用我管理的直接整数会更好吗?
【问题讨论】:
共有三种数组,每种的 Length 工作方式不同:
动态数组:这些被实现为指针。指针指向第一个数组元素,但在该元素“后面”(距数组开头的负偏移量)是两个额外的整数值,表示数组的长度和引用计数。 Length 读取该值。这与 string 类型相同。
静态数组:编译器知道数组的长度,所以Length是一个编译时常量。
开放数组:开放数组参数的长度作为单独的参数传递。编译器知道在哪里可以找到该参数,因此它将Length 替换为对该参数值的读取。
【讨论】:
不要忘记动态数组的布局等在 64 位版本的 Delphi 中会发生变化,因此任何依赖于在特定偏移处查找长度的代码都会中断。
我建议只使用Length()。如果您在循环中使用它,可能想要缓存它,但不要忘记 for 循环已经缓存了循环的终止边界。
【讨论】:
是的,实际上还有两个带有动态数组的附加字段。首先是数组中第一个元素偏移量为 -4 字节的元素数量,而在 -8 字节偏移量处是引用计数。详细解释见Rudy's article。
对于第二个问题,您必须使用SetLength 来调整动态数组的大小,因此无论如何内部的“长度”字段都是可用的。我认为额外的尺寸跟踪没有多大用处。
【讨论】:
既然 Rob Kennedy 对你的问题的第一部分给出了如此好的答案,我将只解决第二个问题:
对于性能关键部分,不使用 Length() 而是使用我管理的直接整数会更好吗?
绝对不是。首先,正如 Rob 所提到的,编译器会非常快速地访问信息,在动态的情况下通过在数组开始之前读取固定偏移量,在静态的情况下使用编译时常量,并在开放数组的情况下传递隐藏参数,您不会获得任何性能改进。
其次,由您管理的直接整数不会更快,但实际上会使用更多内存(与 Delphi 已经为动态和开放数组提供的整数一起分配的额外整数,以及完全在这种情况下的额外整数静态数组)。
即使您直接读取 Delphi 已经为动态数组存储的值,您也不会获得任何超过 Length() 的性能,并且如果该数组的隐藏标头的内部表示在未来发生变化,您的代码可能会被破坏。
【讨论】:
是否有一个内部的、隐藏的整数
是的。
不使用 Length() 而是使用我管理的直接整数?
没关系。
参见Addressing pointersRudy Velthuis 文章中的Dynamic arrays 项目。
附:你也可以hit F1 button。
【讨论】:
Length很容易出错 - 不再有单一真理来源。