Есть ли какие-либо преимущества в использовании параметров const с порядковым типом?

32

Я знаю, что параметры строковой маркировки const могут иметь огромную разницу в производительности, но как насчет порядковых типов? Я могу получить что-либо, сделав их const?

Я всегда использовал параметры const при обработке строк, но никогда не для Integer, Pointer, экземпляров классов и т.д.

При использовании const мне часто приходится создавать дополнительные временные переменные, которые заменяют теперь защищенные от записи параметры, поэтому мне интересно: я получаю что-либо от маркировки порядковых параметров как const?

Теги:

5 ответов

41
Лучший ответ

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

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

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

  • 0
    +1 конечно более удовлетворительное объяснение, чем мое собственное
  • 14
    Ваш первый абзац неверен в отношении строк. Строки всегда передаются в виде четырехбайтовых указателей. Const подавляет код в прологе и эпилоге функции, который обновляет счетчик ссылок строки. То же самое касается параметров интерфейса и динамических массивов. Аналогично, записи передаются в виде указателей. Const просто подавляет код пролога, который копирует запись в локальный стек функции. Другими словами, const не влияет на сторону вызывающей функции. Это влияет только на получателя вызова.
Показать ещё 4 комментария
16

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

  • 3
    Хороший вопрос, но разве этого недостаточно, чтобы НЕ указывать параметр var, чтобы прояснить свое намерение?
  • 2
    Smasher, компилятор не делает различий между var и соглашением по умолчанию, поскольку вам разрешено делать с аргументом в методе.
Показать ещё 3 комментария
8

Объявление порядковых типов const не имеет значения, потому что они копируются в любом случае (по умолчанию), поэтому любые изменения в переменной не влияют на исходную переменную.

procedure Foo (Val : Integer)
begin
Val := 2;
end;
...
SomeVar := 3;
Foo (SomeVar);
Assert (SomeVar = 3);

ИМХО, объявляющее порядковые типы const, не имеет смысла, и, как вы говорите, требуется часто вводить локальные переменные.

  • 2
    У Крейга есть правильная точка зрения. Есть веская причина объявить порядковый номер как const; только не по причинам производительности.
1

Это зависит от того, насколько сложна ваша рутина и как она используется. Если он используется во многих местах и ​​требует, чтобы значение оставалось неизменным, объявите его как "const", чтобы сделать его очищенным и безопасным. Для типа string возникла ошибка (для Delphi 7, когда я пень на ней), которая вызывает повреждение памяти, если объявляется как "const". Ниже приведены примеры кода

type
  TFoo = class 
  private
     FStr: string;
  public
     procedure DoFoo(const AStr: string);
     begin
        FStr := AStr; //the trouble code 1
        ......
     end;
     procedure DoFoo2;
     begin
        .....
        DoFoo(FStr);  //the trouble code 2
     end;
  end;
0

Там огромное увеличение скорости с помощью Const с строками:

function test(k: string): string;
begin
  Result := k;
end;

function test2(Const k: string): string;
begin
  Result := k;
end;

function test3(Var k: string): string;
begin
  Result := k;
end;

procedure TForm1.Button1Click(Sender: TObject);
Var a: Integer;
    s,b: string;
    x: Int64;
begin
  s := 'jkdfjklf lkjj3i2ej39ijkl  jkl2eje23 io3je32 e832 eu283 89389e3jio3 j938j 839 d983j9';

  PerfTimerInit;
  for a := 1 to 10000000 do
   b := test(s);
  x := PerfTimerStopMS;
  Memo1.Lines.Add('default: '+x.ToString);

  PerfTimerInit;
  for a := 1 to 10000000 do
   b := test2(s);
  x := PerfTimerStopMS;
  Memo1.Lines.Add('const: '+x.ToString);

  PerfTimerInit;
  for a := 1 to 10000000 do
   b := test3(s);
  x := PerfTimerStopMS;
  Memo1.Lines.Add('var: '+x.ToString);
end;

default: 443 const: 320 var: 325

default: 444 const: 303 var: 310

default: 444 const: 302 var: 305

То же самое с целыми:

default: 142 const: 13 var: 14

Интересно, однако, что в 64-битной версии практически нет разницы со строками (режим по умолчанию только немного медленнее, чем Const):

default: 352 const: 313 var: 314

Ещё вопросы

Сообщество Overcoder
Наверх
Меню