Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why this copy data from a point wrong?

this is my sample code :

type
  PData = ^TData;
  TData = record
    str : string;
    strlist : TStringList;
  end;

var
  P1 : PData;
  P2 : PData;
  P3 : PData;
  P4 : PData;
begin
  New(P1);
  New(P2);
  P1.str := 'string';
  // copy
  P2^ := P1^;
  P2.str := P2.str + '_copy';
  Memo1.Lines.Add('This is P1:' + P1.str); //This is P1:string
  Memo1.Lines.Add('This is P2:' + P2.str); //This is P2:string_copy

  // so change P2'Data didn't change P1's Data
  // but this :
  New(P3);
  New(P4);
  P3.str := 'string';
  P3.strlist := TStringList.Create;
  P3.strlist.Add('one line');
  // copy
  P4^ := P3^;
  // just add P4's data
  P4.strlist.Add('two line');
  Memo1.Lines.Add('P3''s Data:' + IntToStr(P3.strlist.Count));
  Memo1.Lines.Add(P3.strlist.Text);
  Memo1.Lines.Add('P4''s Data:' + IntToStr(P4.strlist.Count));
  Memo1.Lines.Add(P4.strlist.Text);
  {
   P3's Data:2
   one line
   two line

   P4's Data:2
   one line
   two line
  }
end;

why when copy point data with a class , it will change raw data , but when data is string use P1^ := P2^ copy point data does not change raw data.

like image 529
Hanlin Avatar asked Dec 20 '22 07:12

Hanlin


2 Answers

String is somewhat of a Delphi-managed special entity. In particular, Delphi uses a Copy-On-Write strategy, i.e. when you do P2^ := P1^;, P1.str and P2.str both point to the same string object. Delphi keeps track via an internal reference count how many references to the string object exist.

As soon as you do a write operation like P2.str := P2.str + '_copy', Delphi recognises that the string is in use more than once and creates an own copy for P2.str. This all happens in the background and normally you don't notice this.

On the other hand, P3.strlist and P4.strlist are ordinary pointers and always point to the same object. There is no automagical copying here whatsoever.

like image 103
Marcellus Avatar answered Dec 24 '22 02:12

Marcellus


Strings are copied on demand. That means when you change the copied string, it will create a new instance of the changed string. For simplicity you can assume that a string copy is a copy of the string data.

When you assign a class instance only a pointer to that instance is copied, not the instance itself. After the copy there is still only one class instance. You can see that from your code as there is only one TStringList.Create in your code.

like image 38
Uwe Raabe Avatar answered Dec 24 '22 02:12

Uwe Raabe