2012-06-12 21 views
15

当我在程序中使用const参数时,它有什么不同?当我在过程的参数中使用“const”时,它会有什么不同?

采取以下步骤,例如:

procedure DoSomething(Sender: TObject; const Text: String; var Reply: String); 
begin 
    //Text is read-only and Reply will be passed back wherever DoSomething() was called 
    Reply:= Text; 
end; 

参数Text: Stringconst使得前缀(据我所知),该值的拷贝进行和使用 - 和是只读的。我想知道的是,如果不在那里放置const,它会如何影响应用程序?也许是一种表演技巧?

+1

在这里回答? http://stackoverflow.com/a/1601124/496736 – 2012-06-12 17:25:23

+2

在大多数情况下,我认为将所有仅用于输入的参数标记为“const”的主要好处是,程序员将获得额外的帮助,避免愚蠢错误。 –

+1

@Andreas令人讨厌的是'const'需要包含在接口和实现中。这是C++击败Delphi的一个领域。 –

回答

22

综观documentation状态:

“使用常量允许编译器优化为结构化的代码 - 和字符串型参数它还提供了对通过引用无意将参数传递给另一个例程的保障”

在字符串的情况下,例如优化意味着当传递为const时没有额外的计数。同样以const传递而不是意味着它是一个副本。通常它会作为参考内部传递,因为编译器确保无法对其进行写入访问。

一些非常有趣的文章,完全地了解发生了什么引擎盖下回事:

http://delphitools.info/2010/07/28/all-hail-the-const-parameters

http://vcldeveloper.com/articles/different-function-parameter-modifiers-in-delphi

编辑:

一个简单的例子表明,常量可能导致路过内部参考:

program Project1; 

{$APPTYPE CONSOLE} 

type 
    PMyRecord = ^TMyRecord; 
    TMyRecord = record 
    Value1: Cardinal; 
    Value2: Cardinal; 
    end; 

procedure PassAsConst(const r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

procedure PassByVal(r: TMyRecord); 
begin 
    PMyRecord(@r).Value1 := 3333; 
    PMyRecord(@r).Value2 := 4444; 
end; 

var 
    r: TMyRecord; 
begin 
    r.Value1 := 1111; 
    r.Value2 := 2222; 
    PassByVal(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    PassAsConst(r); 
    Writeln(r.Value1); 
    Writeln(r.Value2); 

    Readln; 
end. 
+3

FWIW:对于**如何通过**,参数是否为常量无关紧要。如果它没有明确声明为'var'或'out',那么它将被**传递**,对于const或非const来说是相同的。通常,大于寄存器大小的项目(比如32位)将通过引用**传递**,无论它们是否为常量。常量和非常量之间的唯一区别在于,对于非常量,隐藏代码在将项目复制到本地存储的开始时插入。对于const,只允许读取引用,所以这个复制代码丢失,直接使用传递的引用。 –

6

如果您没有const前缀,编译器必须假定您将更改该参数。这意味着要复制它并设置一个隐藏的try ...最后来处理本地的字符串变量,所以有时const会产生显着的性能提升。它还使生成的代码更小。

+0

我应该补充说,德尔福2007 - 这是我安装的最新版本。我更高级的编译器可能会检测到一个参数实际上并没有被用作一个变量,即使没有const前缀也不会复制它,但这些优化类型历来不是Delphi研发团队的重点。 –

+0

在Delphi的所有版本中都知道const参数,即在D2007之前:无需复制结构,如果它们通过引用传递(这取决于它们的大小),本地存储并且不需要做引用计数。 –

1

除了之前使用const的效率答案(即,编译器不需要复制该变量),如果使用带有Interface参数的const,它将阻止触发ref计数。

+0

这是此行为的原因:http://qc.embarcadero.com/wc/qcmain.aspx?d=75036 –

+3

缺少引用计数对于接口和字符串是相同的。你所说的关于接口的内容并不是“除了”关于字符串的东西。 *变量*一直被复制,但是复制这些变量很便宜,因为它只是复制指针的值,有时不过是将值从一个寄存器复制到另一个寄存器。 –

相关问题