Строки AnsiString

Вверх  Предыдущий  Следующий

AnsiStrings это строки, которые не имеют ограничение по длине (Начиная с версии 3.0 Free Pascal). Для их ведется подсчет количества ссылок на них, и гарантируется что они будут завершены нулем.

Внутренне, AnsiString интерпретируется как указатель: фактически содержимое строки находится в "куче", в ней выделяется столько памяти, сколько необходимо для хранения содержимого строки.

Если не определена кодовая страница, то берётся кодовая страница системы по умолчанию. Эта кодовая страница определяется константой DefaultSystemCodePage в модуле System.

Это все обрабатывается  прозрачно для программиста, то есть ими можно управлять как обычными короткими строками. AnsiStrings может быть определен, используя предопределенный тип AnsiString.или используя ключевое слово String в режиме {$H+}.

Замечание:

Завершающий нуль не означает, что нулевые символы (char(0) или #0) не могут использоваться внутри строки: завершение нулём не используется внутри, но поддерживается для удобства использования с внешними подпрограммами, которые ожидают завершенную нулем строку (как делают большинство подпрограмм C).

Если включена директива переключатель {$H}, то определение строки, использует ключевое слово String не содержащее спецификатора длины, будет расцениваться как AnsiString. Если будет присутствовать спецификатор длины, то будет использоваться тип ShortString, независимо от наличия директивы {$H}.

Если строка пустая (''), то внутреннее представление строки — указатель, равный Nil. Если строка не пуста, то указатель указывает на структуру в динамической памяти.

Внутреннее представление в виде указателя, и автоматическое завершение нулевым символом позволяет преобразовать тип AnsiString к PChar. Когда строка пуста (в таком случае указатель равен Nil) компилятор удостоверяется, что преобразованный тип PChar указывает на нулевой байт.

Присвоение одного AnsiString другому не приводит к фактическому перемещению строки. Оператор

  S2:=S1;

приводит к тому что счетчик ссылок указывающих на S2 уменьшается на 1, а указывающих на S1 увеличивается на 1, и наконец S1 (как указатель) копируется в S2. Это - существенное ускорение работы кода.

Если счетчик ссылок строки достигает нуля, то память, занятая строкой, освобождается автоматически, и указатель устанавливается в Nil, таким образом, не возникают утечки памяти.

При объявлении переменной типа AnsiString, компилятор Free Pascal первоначально выделяет память только для указателя, не больше. Этот указатель гарантировано будет равен Nil, означая, что строка первоначально пуста. Это истинно для локальных и глобальных переменных типа AnsiStrings или переменных которые являются частью структур (массивов, записей или объектов).

Это вносит накладные расходы. Например, объявление,

Var

  A : Array[1..100000] of string;

скопирует значение Nil 100 000 раз в A. Когда A покидает область видимости, счетчик ссылок каждой из 100000 строк будет уменьшен на единицу для каждой строки в отдельности. Все это происходит невидимо для программиста, но при рассмотрении проблем с производительностью, это важно.

Память для содержимого строки будет выделена только тогда, когда строке будет присвоено значение. Если строка выходит из области видимости, то ее счетчик ссылок автоматически уменьшается на 1. Если счетчик ссылок достигает нуля, память, выделенная для строки, освобождается.

Если символу строки, у которой счетчик ссылок больше чем 1, присвоено значение, как в следующих операторах:

S:=T; { количество ссылок на S и T в настоящее время равно 2}

S[I]:='@';

то перед присвоением создается копия строки. Этот подход известен как копирование при записи. Существует возможность получить строку с количеством ссылок гарантировано равным 1 используя функцию UniqueString.

S:=T;

R:=T; // Счетчик ссылок Т не меньше 3

UniqueString(T);

// Счетчик ссылок Т гарантировано равен 1

Рекомендуется делать это, при преобразовании типа AnsiString к типу PChar и при передаче его в подпрограмму C, которая изменяет переданную строку.

Чтобы получить длину строки AnsiString нужно использовать функцию Length: длина строки не находится в нулевом символе. Конструкция

L:=ord(S[0]);

была допустима в Turbo Pascal для ShortStrings, но она не корректна для AnsiStrings. Компилятор выдаст предупреждение, если встретятся с такой конструкцией.

Чтобы установить длину строки AnsiString, нужно использовать функцию SetLength. Константы AnsiStrings имеют счетчик ссылок равный -1 и обрабатываются особенно. То же замечание нужно сделать и относительно функции Length: конструкция

L:=12;

S[0]:=Char(L);

была допустима в Turbo Pascal для ShortStrings, но она не корректна для AnsiStrings. Компилятор выдаст предупреждение, если встретятся с такой конструкцией.

AnsiStrings преобразуются компилятором в ShortStrings если нужно, это означает, что AnsiStrings и ShortStrings могут быть "смешаны" (в коде).

AnsiStrings может быть преобразован к типу PChar или типам Pointer:

Var P : Pointer;

  PC : PChar;

  S : AnsiString;

begin

S :='Это AnsiString';

PC:=Pchar(S);

P :=Pointer(S);

Между двумя преобразованиями типов есть различие. Когда пустая AnsiString строка будет преобразована к типу указатель, указатель будет равен Nil. Если пустая AnsiString строка будет преобразована к типу PChar, то результатом будет указатель на нулевой байт (пустую PChar строку).

Результатом такого преобразования следует пользоваться с осторожностью. Лучше использовать результат такого приведения только для чтения, т.е. он подходит только как параметр для передачи в процедуру, которая нуждается в аргументе-константе типа PChar.

Поэтому не желательно делать приведения типов в следующих случаях:

1.выражениях.

2.строках, у которых счетчик ссылок, больше чем 1. В этом случае Вы должны вызвать Uniquestring, чтобы гарантировать, что у строки счетчик ссылок равен 1.