【问题标题】:How does the Length() function in Delphi work?Delphi 中的 Length() 函数是如何工作的?
【发布时间】:2010-10-22 00:12:24
【问题描述】:
  • 在 C++ 等其他语言中,您必须自己跟踪数组长度 - Delphi 如何知道我的数组长度?是否有一个内部的隐藏整数?

  • 对于性能关键部分,不使用 Length() 而是使用我管理的直接整数会更好吗?

【问题讨论】:

    标签: arrays delphi


    【解决方案1】:

    共有三种数组,每种的 Length 工作方式不同:

    • 动态数组:这些被实现为指针。指针指向第一个数组元素,但在该元素“后面”(距数组开头的负偏移量)是两个额外的整数值,表示数组的长度和引用计数。 Length 读取该值。这与 string 类型相同。

    • 静态数组:编译器知道数组的长度,所以Length是一个编译时常量。

    • 开放数组:开放数组参数的长度作为单独的参数传递。编译器知道在哪里可以找到该参数,因此它将Length 替换为对该参数值的读取。

    【讨论】:

    • 屏幕类型的某些精度:自 Delphi 2009 以来,有第三个“额外整数”,它编码字符串中每个字符的大小(以字节为单位)(即,1 表示 AnsiString,2 表示UnicodeString)和字符集(用于 AnsiString) - 作为两个单词聚合为一个整数。从 Delphi 2007 开始,length() 是一个读取隐藏长度整数的内联函数,速度非常快。所以使用 length() 非常快,比使用 strlen 更快(我强调这一点,因为你来自 c/c++ 世界)。
    • @A. Bouchez:在您的第一句话中:屏幕类型 == 字符串类型?
    【解决方案2】:

    不要忘记动态数组的布局等在 64 位版本的 Delphi 中会发生变化,因此任何依赖于在特定偏移处查找长度的代码都会中断。

    我建议只使用Length()。如果您在循环中使用它,可能想要缓存它,但不要忘记 for 循环已经缓存了循环的终止边界。

    【讨论】:

      【解决方案3】:

      是的,实际上还有两个带有动态数组的附加字段。首先是数组中第一个元素偏移量为 -4 字节的元素数量,而在 -8 字节偏移量处是引用计数。详细解释见Rudy's article

      对于第二个问题,您必须使用SetLength 来调整动态数组的大小,因此无论如何内部的“长度”字段都是可用的。我认为额外的尺寸跟踪没有多大用处。

      【讨论】:

        【解决方案4】:

        既然 Rob Kennedy 对你的问题的第一部分给出了如此好的答案,我将只解决第二个问题:

        对于性能关键部分,不使用 Length() 而是使用我管理的直接整数会更好吗?

        绝对不是。首先,正如 Rob 所提到的,编译器会非常快速地访问信息,在动态的情况下通过在数组开始之前读取固定偏移量,在静态的情况下使用编译时常量,并在开放数组的情况下传递隐藏参数,您不会获得任何性能改进。

        其次,由您管理的直接整数不会更快,但实际上会使用更多内存(与 Delphi 已经为动态和开放数组提供的整数一起分配的额外整数,以及完全在这种情况下的额外整数静态数组)。

        即使您直接读取 Delphi 已经为动态数组存储的值,您也不会获得任何超过 Length() 的性能,并且如果该数组的隐藏标头的内部表示在未来发生变化,您的代码可能会被破坏。

        【讨论】:

          【解决方案5】:

          是否有一个内部的、隐藏的整数

          是的。

          不使用 Length() 而是使用我管理的直接整数?

          没关系。

          参见Addressing pointersRudy Velthuis 文章中的Dynamic arrays 项目。

          附:你也可以hit F1 button

          【讨论】:

          • 确实很重要,因为它会浪费 CPU 周期、内存并且容易出错。
          • 如何容易出错?我从来没有遇到过 Length() 无法正常工作或返回错误值的问题……否则它怎么会容易出错?
          • @DavidM,我刚刚注意到您的评论有“一点”延迟。我我的意思是使用Length很容易出错 - 不再有单一真理来源。
          猜你喜欢
          • 2014-12-08
          • 1970-01-01
          • 2017-03-24
          • 1970-01-01
          • 1970-01-01
          • 2021-03-30
          • 2020-07-18
          • 2015-11-08
          • 2017-05-21
          相关资源
          最近更新 更多