多个字符串变量真的可以引用相同的数据吗?

时间:2011-03-16 15:10:59

标签: string delphi reference-counting

根据互联网上的信息,我发现了以下两个变量 指向记忆中的同一个地方。

有没有人可以提出一个代码示例来证明实际上它是正确的(例如,通过更改第一个变量中的一个字母并看到这个变化在第二个变量中可见)?

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

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

5 个答案:

答案 0 :(得分:8)

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

结果为True,是的,ab指向相同的数据。

但请注意

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,因为ab不同的字符串(指针)变量,所以在内存中的某个位置(@a )是a的数据地址,其他地方(@b)是b数据的地址。第一个示例显示内存中的这两个位置包含相同的地址,即ab包含相同的数据。

答案 1 :(得分:3)

通常Delphi对字符串使用'copy-on-write'语义,所以你需要一种黑客才能做到这一点,例如:

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;

答案 2 :(得分:1)

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;

答案 3 :(得分:0)

你的问题对我来说不是很清楚。 如果你这样做:

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

我想你会看到它......

答案 4 :(得分:0)

使用此代码可以更清楚

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;