Я знаю, что параметры строковой маркировки const
могут иметь огромную разницу в производительности, но как насчет порядковых типов? Я могу получить что-либо, сделав их const
?
Я всегда использовал параметры const
при обработке строк, но никогда не для Integer
, Pointer
, экземпляров классов и т.д.
При использовании const
мне часто приходится создавать дополнительные временные переменные, которые заменяют теперь защищенные от записи параметры, поэтому мне интересно: я получаю что-либо от маркировки порядковых параметров как const
?
Вам нужно понять причину, чтобы избежать "компромиссного программирования". Маркировка строк как const приводит к разнице в производительности, потому что вам больше не нужно использовать взаимоблокированный приращение и уменьшение количества ссылок на строку, операция, которая на самом деле становится более дорогой, не менее, со временем, поскольку больше ядер означает больше работы, которая чтобы сохранить синхронизацию атомных операций. Это безопасно делать, поскольку компилятор принуждает ограничение "эта переменная не изменяться".
Для ординалов, которые обычно составляют 4 байта или меньше, нет увеличения производительности. Использование const, поскольку оптимизация работает только тогда, когда вы используете типы значений, превышающие 4 байта, такие как массивы или записи или типы с подсчетом ссылок, такие как строки и интерфейсы.
Однако есть еще одно важное преимущество: читаемость кода. Если вы передадите что-то как const, и это не имеет никакого значения для компилятора, оно все равно может повлиять на вас, так как вы можете прочитать код и увидеть, что его намерение состояло в том, быть изменен. Это может быть значительным, если вы еще не видели код раньше (кто-то другой его написал), или если вы вернетесь к нему через долгое время и не помните точно, что вы думаете, когда вы его первоначально написали.
Вы не можете случайно относиться к ним как к параметрам var
и компилировать свой код. Таким образом, ваши намерения становятся ясными.
Объявление порядковых типов const не имеет значения, потому что они копируются в любом случае (по умолчанию), поэтому любые изменения в переменной не влияют на исходную переменную.
procedure Foo (Val : Integer)
begin
Val := 2;
end;
...
SomeVar := 3;
Foo (SomeVar);
Assert (SomeVar = 3);
ИМХО, объявляющее порядковые типы const, не имеет смысла, и, как вы говорите, требуется часто вводить локальные переменные.
Это зависит от того, насколько сложна ваша рутина и как она используется. Если он используется во многих местах и требует, чтобы значение оставалось неизменным, объявите его как "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;
Там огромное увеличение скорости с помощью 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
Const
подавляет код в прологе и эпилоге функции, который обновляет счетчик ссылок строки. То же самое касается параметров интерфейса и динамических массивов. Аналогично, записи передаются в виде указателей.Const
просто подавляет код пролога, который копирует запись в локальный стек функции. Другими словами,const
не влияет на сторону вызывающей функции. Это влияет только на получателя вызова.