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

时间:2012-06-12 17:12:23

标签: delphi parameters constants

在程序中使用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放在那里,这对应用程序有何影响?也许是表演技巧?

4 个答案:

答案 0 :(得分:23)

查看documentation州:

“使用const允许编译器优化结构化和字符串类型参数的代码。它还提供了防止通过引用另一个例程无意中传递参数的安全措施。”

例如,对于字符串,优化意味着在作为const传递时没有额外的引用计数。另外作为const传递意味着它是副本。它通常在内部作为引用传递,因为编译器确保没有对它的写访问权。

一些非常有趣的文章要完全理解幕后发生的事情:

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

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

编辑:

一个简单的例子,表明const可能导致内部传递:

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.

答案 1 :(得分:7)

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

当在函数中使用Activity参数时,向Delphi编译器保证不会从该函数调用任何其他函数,至少在将所有这些const string参数复制到其中之前您将拥有的局部变量。

https://github.com/the-Arioch/XE2_AutoOpenUnit/blob/master/Delphi_String_Bug/Girli_str_2xFree_Minimized.dpr

https://plus.google.com/+AriochThe/posts/WB3toSpAdfA

const string

由于volatile字符串和const字符串实际上是两种不同的类型-经典编译器将它们区别对待-应该添加数据转换:当调用const-string函数传递时,其易失性字符串参数Delphi可以增加使用计数器并在函数退出后减小它。将const-strings参数向下传递到下一个const-string函数将是现在的样子,一旦编译器将volatile字符串类型转换为const字符串,它将保持不变。

遗憾的是,事实并非如此。还有龙。

因此,如果您的函数具有const字符串参数-请不要从中调用它,也不要将这些参数缓存到本地vars中。