Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 哪种方法处理一系列记录更有效?_Delphi - Fatal编程技术网

Delphi 哪种方法处理一系列记录更有效?

Delphi 哪种方法处理一系列记录更有效?,delphi,Delphi,什么是更有效的方法 FUserRecords[I].CurrentInput:=FUserRecords[I].CurrentInput+typedWords; 或 在您描述的案例中,第一个示例将是最有效的 记录是值类型,因此在执行此操作时: userRec:=FUserRecords[I]; 实际上,您正在将数组中记录的内容复制到局部变量中。当你做相反的操作时,你又在复制信息。如果在数组上进行迭代,如果数组和记录非常大,那么迭代速度可能会非常慢 如果要沿着第二条路径前进,为了加快速度,可以

什么是更有效的方法

FUserRecords[I].CurrentInput:=FUserRecords[I].CurrentInput+typedWords;


在您描述的案例中,第一个示例将是最有效的

记录是值类型,因此在执行此操作时:

userRec:=FUserRecords[I];
实际上,您正在将数组中记录的内容复制到局部变量中。当你做相反的操作时,你又在复制信息。如果在数组上进行迭代,如果数组和记录非常大,那么迭代速度可能会非常慢

如果要沿着第二条路径前进,为了加快速度,可以使用指向记录的指针直接操作数组中的记录,如下所示:

type
  TUserRec = record
    CurrentInput: string;
  end;
  PUserRec = ^TUserRec;

var
  LUserRec: PUserRec;
...
LUserRec := @FUserRecords[I];
LUserRec^.CurrentInput := LUserRec^.CurrentInput + typedWords;
(正如评论中所讨论的,插入符号(^)是可选的。我只是为了完整性才在这里添加它们)

当然,我应该指出的是,只有在存在性能问题的情况下,才需要这样做。在手工编写此类优化之前,对应用程序进行概要分析总是很好的

编辑:对于您正在查看的有关性能问题的所有讨论,需要注意的一点是,如果记录中的大多数数据都是字符串,那么您所展示的示例中损失的大部分性能将出现在字符串连接中,而不是记录操作中

此外,字符串基本上作为指针存储在记录中,因此记录实际上是任何整数等的大小加上字符串指针的大小。因此,当您连接到字符串时,它不会增加记录大小。基本上,您可以将代码中的字符串操作部分视为记录操作的一个单独问题

您在下面的评论中提到,这是用于存储来自多个键盘的输入,我无法想象阵列中会有超过5-10个项目。在这样的规模下,执行这些步骤来优化代码并不能真正提高那么多速度

我相信,您的第一个示例和使用上述代码的指针最终将获得大致相同的性能。你应该使用最容易阅读和理解的方法


N@

速度更快,可读性更强:

with FUserRecords[I] do 
  CurrentInput := CurrentInput + typedWords;

你知道那些实际上没有相同的净效应吗?哎呀。忘了一行!(编辑它!):涂鸦。是的,我忘了写最后一行。好的,我试试看。指针更有效吗?是的,在这种情况下指针会更有效。我还要指出[sic]在Delphi中,解引用操作符是完全可选的。LUserRec^.xyz可以简单地写入LUserRec.xyz并自动取消引用。对于那些对这些捷径所带来的“模糊性”感到震惊的人来说,这可能意味着什么呢?请注意,我们一直在使用对象引用变量(它们是另一个名称的指针)执行此操作。使用第一个选项实际上是唯一的选项。正如Nat指出的,记录是“值”,你不想复制它们。使用指针实现选项2只会使代码变得模糊,并没有任何好处(甚至可能会使事情稍微慢一点)。在使用数组时,Delphi通常会计算到所需字段的偏移量,并使用“基于索引的寻址模式”:这是一条汇编指令,用于读/写一个字大小的字段。如果将其替换为显式指针,您将使用至少两条指令+1个额外寄存器来完成相同的工作。@Deltics:但是P1:=P2与P1^:=P2^不同,为什么在访问字段时取消引用是可选的?Delphi将该操作符设置为可选的事实是一个错误(我将其提交给QC),并且只会导致混淆。对象引用是以不同的方式处理的,您无论如何都不能取消引用它们,它们只能以一种方式使用,它们不是“指针”类型。就连字符串和动态数组都是用指针实现的,var变量是用指针实现的,但它们不是“指针”类型。Delphi应该遵守自己的规则以避免混淆。@ldsandon:Yes,P1:=P2 P1^:=P2^。。。但是P1.xyz:=P2.xyz毫无意义,不应该编译。要使其编译,您必须将^添加到解引用中。但是我们不必这样做,那么“P”是一个模糊的指针(即对象引用),那么为什么我们必须在它没有模糊的情况下这样做呢?这完全没有必要,也不会导致混淆或歧义。你自己也很困惑。。。您发现让Delphi为您处理您提到的任意数量的自动取消引用案例是完全合理的,但在这一案例中,您会抱怨?为什么我要将记录的
typedWords
字段添加到同一记录的
CurrentInput
字段?明白了!问题中的代码并没有做到这一点,这就对您声称的代码更具可读性提出了质疑。另外,请显示您的代码更快。FUserRecords[I]。CurrentInput:=FUserRecords[I]。CurrentInput+typedWords是代码。“with FUserRecords[I]”将只索引(I)和取消引用(.)一次,如果编译器未进行优化的话。下面的代码(有问题的)将把记录分配给局部变量,修改它,然后重新分配。哦,我看到了Rob发现的问题。typedWords可能被误认为是记录的字段(它不应该是记录字段,它是一个全局变量)。但是代码还是可以正常工作的。有一个问题,如果记录有一个名为typedWords的字段,它会使用全局变量的值还是字段的值?这就是
with
的危险之处。它将使用记录中的
typedWords
,而不是全局。这是我没有在回答中给出这个解决方案的唯一原因。。。哦,而且我不想被反恐怖分子激怒!
with FUserRecords[I] do 
  CurrentInput := CurrentInput + typedWords;