Могут ли несколько строковых переменных действительно ссылаться на одни и те же данные? - PullRequest
4 голосов
/ 16 марта 2011

По информации в интернете я обнаружил, что две следующие переменные указать на то же место в памяти.

Может ли кто-нибудь предложить пример кода, чтобы продемонстрировать, что это действительно так (например, путем изменения одной буквы в 1-й переменной и увидеть, что это изменение видно из второй переменной)?

procedure TForm1.Button1Click(Sender: TObject);
var
  a, b: String;
begin
  a := 'Test';
  b := a;

  showmessage (a);
  showmessage (b);
end;

Ответы [ 5 ]

8 голосов
/ 16 марта 2011
procedure TForm4.FormCreate(Sender: TObject);
var
  a, b: string;
begin
  a := 'Test';
  b := a;
  ShowMessage(BoolToStr(pointer(a) = pointer(b), true));
end;

Результат - True, поэтому да, a и b указывают на одни и те же данные.

Однако обратите внимание, что отображается

procedure TForm4.FormCreate(Sender: TObject);
var
  a, b: string;
begin
  a := 'Test';
  b := a;
  b := 'Test2';
  ShowMessage(BoolToStr(pointer(a) = pointer(b), true));
end;

False, как и должно быть.

Кроме того, обратите внимание, что

procedure TForm4.FormCreate(Sender: TObject);
var
  a, b: string;
begin
  a := 'Test';
  b := a;
  ShowMessage(BoolToStr(@a = @b, true));
end;

также отображает False, поскольку a и b отличаются строковые (указатель) переменные, поэтому в некотором месте в памяти (@a) находится адрес данных a, а где-то еще (@b) - адрес данных b.Первый пример показывает, что эти два места в памяти содержат один и тот же адрес, то есть a и b содержат одинаковые данные.

3 голосов
/ 16 марта 2011

Обычно Delphi использует семантику «копировать при записи» для строк, поэтому вам нужно что-то вроде хака, например:

procedure TForm13.Button1Click(Sender: TObject);
const
  Test: string = '12345';

var
  S1, S2: string;
  P: PChar;

begin
  SetString(S1, PChar(Test), 5);
// we need to copy '12345' string from readonly memory to heap
  S2:= S1;
// Now both S1 and S2 points to the same memory

  P:= Pointer(S1);
  P^:= 'A';
  ShowMessage(S2);  // 'A2345'
end;
1 голос
/ 16 марта 2011
var
  a, b: string;
begin
  a := 'Test';
  a := a + '!'; // added after Rob's comment below, 
                // makes sure a points to an allocation on the heap
  b := a;
  PChar(b)[3] := 'T';
  ShowMessage(a); //--> TesT!
end;
0 голосов
/ 16 марта 2011

OK может быть более понятным с этим кодом

procedure TForm1.FormCreate(Sender: TObject);

var
  a, b , s : string;
  p : pointer;
begin
  a := 'Test';
  b := a;
// we see the 2 diff. var pointing on the same adress
  s := Format('%p -> %p / %p -> %p', [@pointer(a),pointer(a),@pointer(b),pointer(b)] );
  ShowMessage( 'first : '+s);
// we see the 2 diff. var pointing on different adresses
  a := 'Test2';
  s := Format('%p -> %p / %p -> %p', [@pointer(a),pointer(a),@pointer(b),pointer(b)] );
  ShowMessage( 'second : '+s);
end;
0 голосов
/ 16 марта 2011

Ваш вопрос не очень понятен для меня. Если вы делаете:

begin 
  a := 'Test';
  b := a;
  a := a+'HH';
  showmessage (a);
  showmessage (b); 
end;

Думаю, вы это увидите ...

...