2014-06-27 162 views
1

在一些代码,我维护,我看到TClientDataSet.OnCalcFields事件处理程序使用两种不同的方法:编译器是否优化(关闭)相同的FieldByName调用?

with DataSet do 
begin 
    // 1. Call FieldByName twice 
    if AMinDate > FieldByName(SPlanAllocatieFromDate).AsDateTime then 
     AMinDate := FieldByName(sPlanAllocatieFromDate).AsDateTime; 
    // 2. Put the retrieved FieldByName value in a temp var 
    lEmpID := FieldByName(SPlanAllocatieEmpID).AsInteger; 
    if lEmpID <> 0 then lTSAllocatedEmpIDs.Add(IntToStr(lEmpID)); 
end; 

将编译器(德尔福XE2的Win32应用程序)优化方法2使用一个临时变种?两个FieldByNames非常接近,你甚至可以说嵌套

如果不是,我应该重写1.因为OnCalcFields经常执行。

顺便说一句。我知道Fields []与FieldByName()的比较,或者在运行EOF循环时使用temp TField var,这些都不是问题。

+0

我个人不会认为编译器优化是好的。我通常会在谨慎的方面犯错,并且指定一个临时变量并消除所有疑问。 –

+0

@Johan,看到注释*“BTW。我知道Fields []与FieldByName()...”*在问题中;-) – TLama

+0

据我所知,只有'gcc'足够聪明才能做到这一点。 –

回答

7

没有版本的Delphi编译器可以做这样的事情。

这样的优化将要求编译器能够证明两个对FieldByName的调用总是会给出相同的结果,并且目前没有规定将方法标记为确定性的。

请注意,在这种情况下,理论上(如果实际上不太可能)两个调用不会给出相同的结果是完全可能的。如果不同的线程从第一个和第二个调用之间的集合中删除一个字段。一般来说,编译器不知道或关心呼叫站点实际执行的特定方法调用。

+1

不仅如此,而且函数调用没有副作用 –

+0

是的,也是如此。 –

5

编译器是否优化(关闭)相同的FieldByName调用?

不,它不。

编译器不会在函数调用内部查看内部的内容。因此无法证明连续调用函数返回的值是相同的。同样,它无法证明该功能没有副作用。这些是考虑优化的两个先决条件。

您将需要自己执行优化,方法是明确添加并使用局部变量来将单次调用返回的值存储到FieldByName


除了考虑性能,我认为使用局部变量来保存字段在语义上要好得多。这让读者清楚,所有行为都是在同一个领域进行的。仅凭这个理由就足以说服我做出你所描述的改变。不要重复自己。

虽然我们处于代码审查模式,但您可能会考虑重新考虑使用with

+1

不知道这是你的意思,但在性能方面,最好使用跨OnCalcFields调用持续存在的字段对象,因为按名称查找字段是一个昂贵的过程和OnCalcFields甚至可以被称为令人惊讶的往往是一些情况。当然,传统的“坚持的领域”满足这一点。 – MartynA

+1

@MartynA绝对。我的答案的第二部分指出,除了性能优势之外,如果仅仅执行一次字段查找,代码会更好。 –