2010-09-27 1 views
0

В чем разница междуWrtiting строка TMemoryStream - Указатель на строку

этого:

SourceString := 'I am doing just fine!';  
MemoryStream.ReadBuffer(Pointer(SourceString)^, xxx); 

(полный исходный код доступен здесь: http://edn.embarcadero.com/article/26416)

и этот код (шахты):

SetLength(SourceString, xxx); 
MemoryStream.ReadBuffer(SourceString[1], xxx); 
  1. Я действительно должен использовать Pointer (SourceString)^или SourceString [1], также хорошо?
  2. Код (оба из них) будет работать с Delphi 2010 (unicode)?

ответ

2

1: Версия SourceString[1] более читаема. Я предпочитаю не работать с указателями, когда они не являются полностью необходимыми.

2: Этот код будет не Работа с Unicode. Вам придется умножить его: xxx * sizeof(Char). (Это будет работать как с версиями Delphi, так и после Unicode.) Но если вы не используете сильно несимметричные символы, это будет большой пустой тратой пространства. То, что я предпочитаю делать это:.

procedure TStreamEx.WriteString(const data: string); 
var 
    len: cardinal; 
    oString: UTF8String; 
begin 
    oString := UTF8String(data); 
    len := length(oString); 
    self.WriteBuffer(len, 4); 
    if len > 0 then 
    self.WriteBuffer(oString[1], len); 
end; 

procedure TStreamEx.ReadString(const data: string); 
var 
    len: cardinal; 
    iString: UTF8String; 
begin 
    self.ReadBuffer(len, 4); 
    if len > 0 then 
    begin 
    SetLength(iString, len); 
    self.ReadBuffer(iString[1], len); 
    result := string(iString); 
    end 
    else result := ''; 
end; 

(Это часть class helper for TStream я написал, что делает его намного легче читать и писать различные вещи, и из потоков Но если вам не нравится класс помощников, оно не должно быть слишком трудно приспособить основную идею в другой формат)

+0

«Это часть помощника класса для TStream». Мой код также относится к моему помощнику класса. Хотя я был уверен, что он не будет работать с Delphi 2010, если я не изменю строку на AnsiString (что я просто недавно). Хотя, я не очень заинтересован в сохранении UNICOE, я признаю, что я обновлю свой код (используя ваш) для поддержки UNICODE. Благодарю. – Ampere

+0

Версия SourceString [1] более читаема - Спасибо за подтверждение Мейсон. Я нашел код на веб-сайте Borland, и я подумал: «Это должно быть что-то с ним, если они дают его в качестве примера». Какой смысл делать это сложнее, чем нужно? – Ampere

+5

Когда вы включили проверку диапазона (и вы всегда должны иметь проверку диапазона), тогда 'SourceString [1]' будет вызывать исключение, когда длина равна нулю, тогда как 'Pointer (SourceString)' будет нулевым указателем, и что не будет разыменовываться, поскольку счет байта, который вы передаете, также равен нулю. См. * Листинг 4 * на [моем веб-сайте] (http://www.cs.wisc.edu/~rkennedy/string-stream). –

2

в сгенерированном коде ассемблерного:.

  • указателя (aString)^ будет передавать адрес строки непосредственно к процедуре/функция/метод;
  • aString [1] вызовет UniqueString, затем передайте строковый адрес процедуре/функции/методу.

Так указатель (aString)^ следует использовать, если вы собираетесь читать данные, но не изменять его.

И aString [1] должен использоваться, если вы собираетесь изменить aString в вызываемой функции.

На практике я использую указатель (aString)^, который производит более эффективный код.

Обратите внимание, что эта неявная UniqueString не так медленно: если текущий счетчик ссылок строки равна 1 (что означает, что есть только одна часть вашего кода, используя строку, которая весьма вероятно), то она возвращает немедленно. Но есть префикс LOCK asm в UniqueString, используемый для проверки значения счетчика ссылок, и использование этого LOCK asm не является многопоточным. Вот почему я стараюсь избегать использования aString [1], когда я кодирую.

Дополнительное примечание: если aString является '', указатель (aString) вернет ноль.

+0

Другими словами, указатель (aString)^быстрее, тогда как aString [1] безопаснее? – Ampere

+0

вы можете сказать это :), но в некоторых случаях неявный вызов UniqueString является обязательным для предотвращения повреждения памяти: вы можете использовать явный вызов UniqueString перед использованием указателя (aString) ^, если вы хотите, чтобы ваш код был как безопасным, так и быстрым –

Смежные вопросы