Какая разница, когда я использую "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: String имеет префикс const, поэтому (насколько мне известно) копия значения создается и используется - и доступна только для чтения. Мне было интересно, как это влияет на приложение иначе, чем если бы я не поставил const там? Возможно, трюк производительности?

Ответы

Ответ 1

В документации говорится:

"Использование const позволяет компилятору оптимизировать код для параметров структурированного и строкового типа, а также обеспечивает защиту от непреднамеренной передачи параметра ссылкой на другую процедуру."

В случае строки, например, средство оптимизации означает, что при передаче в качестве константы нет дополнительной пересчеты. Также, как const, не означает копию. Часто он внутренне передается как ссылка, потому что компилятор не обеспечивает доступа к записи.

Некоторые очень интересные статьи, чтобы полностью понять, что происходит под капотом:

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

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

Edit:

Простой пример, показывающий, что 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.

Ответ 2

Если у вас нет префикса const, компилятор должен предположить, что вы измените параметр. Это означает, что нужно скопировать его и настроить скрытую попытку... наконец, избавиться от локальной строковой переменной, поэтому иногда константа может значительно повысить производительность. Он также уменьшает сгенерированный код.

Ответ 3

В дополнение к предыдущим ответам эффективности при использовании константы (т.е. компилятору не нужно копировать переменную), если вы используете константу с параметром Interface, она предотвращает запуск подсчета ref.