Читать «Фундаментальные алгоритмы и структуры данных в Delphi» онлайн - страница 22
Джулиан М. Бакнелл
Счетчик ссылок присутствует в блоке памяти, поэтому операция
MyOtherString := MyString выполняется очень быстро. Компилятор преобразует это присвоение за два шага: сначала он увеличивает на 1 счетчик ссылок для строки, на которую указывает MyString, а затем устанавливает указатель MyOtherString равным указателю MyString.
Вот и все, что можно сказать об увеличении быстродействия приложения при использовании длинных строк. Все остальные операции со строками будут требовать выделения памяти.
Использование ключевого слова const
Если функции передать строку, которая в процессе выполнения функции не будет изменяться, объявляйте ее как const. В большинстве случаев это исключает скрытое добавление блока try..finally. Если не использовать ключевое слово const, компилятор будет считать, что значение, возможно, будет изменяться, и поэтому вводит скрытую локальную переменную для хранения строки. В начале выполнения функции счетчик ссылок будет увеличен на 1, а в конце - уменьшен на 1. Чтобы гарантировать, что значение счетчика всегда будет уменьшаться, компилятор вставляет скрытый блок try..finally.
В листинге 1.5 приведена функция определения количества гласных в строке.
Листинг 1.5. Подсчет количества гласных в строке
function CountVowels(const S : string): integer;
var
i : integer;
begin
Result := 0;
for i := 1 to length (S) do
if upcase(S[i]) in ['A', 'E', 'I', 'O', 'U'] then
inc(Result);
end;
Если из строки объявления функции убрать ключевое слово const, ее быстродействие снизится приблизительно на 12% - это и есть влияние скрытого блока try..finally.
Осторожность в отношении автоматического преобразования типов
Часто мы используем совместно символы и строки, не обращая на это никакого внимания. Преобразованием типов занимается компилятор, и программист зачастую не подозревает, что происходит на самом деле. Возьмем, например, функцию Pos. Как вы знаете, эта функция возвращает положение подстроки в строке. Если использовать ее для поиска символа:
PosOfCh := Pos(SomeChar, MyString);
нужно помнить, что компилятор автоматически преобразует символ в длинную строку. Он выделит память для строки из кучи, установит длину равной 1 и скопирует в строку символ. Затем вызывается функция Pos. Поскольку фактически будет использоваться скрытая длинная строка, для уменьшения значения счетчика ссылок в функцию будет автоматически добавлен блок try..finally. Функция, приведенная в листинге 1.6, в пять (да-да, в пять!) раз быстрее, несмотря на то, что она была написана на языке Pascal, а не на ассемблере.