Да, я понимаю, что тут никто не пишет на дельфи, но раз уж я иногда что-то пишу о ней, то позвольте мне.

В дельфи есть элемент языка, которым все пренебрегают. Очень крутой. Это атрибут входного параметра const.
Вместо:
function IsStringAbrakadabra(s:string): boolean
Получится:
function IsStringAbrakadabra(const s:string): boolean

Зачем?
Строки в Дельфи ведут учёт ссылок. Каждое присваивание увеличивает счётчик на 1. Каждое зануление - уменьшает его. Поэтому любая функция, которая получает строки, преобразуется компилятором в следующую:
UStrLAsg(s); //увеличить счётчик ссылок
try
//сама функция
finally
UStrLClr(s); //уменьшить счётчик ссылок
end;
Два лишних вызова! И фрейм try..finally (это очень дорогая конструкция). Эта обёртка легко может тратить больше времени, чем сама ваша функция! Скомпилите и посмотрите в ассемблер - инлайнить такую дуру тоже пропадает всякая выгода.

На помощь спешит модификатор const! Он говорит компилятору, что вы клянётесь героиней любимого мультика не трогать полученной строки. Тогда можно учёт ссылок не вести, и фрейм try..finally тоже не нужен. Вместо 60 ассемблерных инструкций ваша функция внезапно компилируется в шесть!

Но это ещё не всё.
Мало добавлять const к строковым параметрам. Строки могут передаваться неявно. Функция, которая получает структуру со строкой внутри, тоже требует учёта ссылок и фрейма try..finally. Даже хуже: вместо прямолинейного UStrLAsg будет вызван AddRefRecord, который с помощью некоего подобия рефлекшна изучает вашу структуру и решает, каким полям нужен какой учёт ссылок. И так в каждой функции!
Дельфи не глупая, и если структуре совсем не нужен учёт ссылок, она поймёт это при компиляции, и фрейм не вставит. Но когда хоть одно поле требует учёта, вы получите пенальти в размере полного разбора всей структуры дважды.

Поэтому ставьте const везде, где можно. Ставьте const всему, что передаёте на копирование во всевозможные "SetSomething" или "InitSomething". В крайнем случае он будет просто подсказкой читающему код.

Ещё очень важная информация: отключайте "String format checking" в настройках компиляции. Всегда. Сразу же. Эту опцию следовало бы назвать "замедлить в три раза все операции со строками, для того, чтобы спрятать от вас чудовищные баги в вашем коде".

@темы: Компьютеры

Комментарии
07.12.2012 в 23:19

>>героиней любимого мультика
какой эвфемизм для вайфу!

А если я таки изменю то что было передано как конст? или оно сразу становится не-леводопустимым?
07.12.2012 в 23:43

zHz00, не-lvalue, да, но иногда всё-таки можно (поля структуры), но в таком случае сам виноват!

На этом основывалась моя офигенная техника, которую на stackoverflow назвали Ugliest delphi hack ever:
type
TCallMaker = record
Param1: string;
Param2: integer;
procedure Call;
begin
SomeProc(Param1, Param2);
end;
end;

function CallMaker: TCallMaker;
begin
//Initialize all params with default values
Result.Param1 := DefaultValue1;
Result.Param2 := DefaultValue2;
end;

with CallMaker do begin
//Set only those params you need changed
Param2 := Value2;
Call;
end;

//This worked until Delphi 2010.
//But now the compiler complains that whatever CallMaker returns is not an lvalue.
//Ha-ha!

function TCallMaker.This: PCallMaker;
begin
Result := @Self;
end;

with CallMaker.This^ do begin
//It's an lvalue now! :)
end;