2013-04-02 18 views
4

這是我的示例代碼:爲什麼從一個點這個拷貝數據錯誤

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; 

爲什麼當有class複製點數據,它會改變原始數據,但如果數據是string使用P1^ := P2^複製點數據不會更改原始數據。

+0

想想這個的最好方法是考慮'string'是一個值類型。它具有值類型語義,即使實現很時髦。如果你有一個智能模型,把'string'放在'Integer'和'Double'的類中,那麼你就不會出錯。 –

回答

5

字符串有點像Delphi管理的特殊實體。特別是,Delphi使用Copy-On-Write策略,即當您執行P2^ := P1^;時,P1.strP2.str都指向相同的字符串對象。 Delphi通過內部引用計數來跟蹤對字符串對象的引用數量。

只要您執行像P2.str := P2.str + '_copy'這樣的寫操作,Delphi就會識別該字符串正在被使用多次,併爲P2.str創建一個自己的副本。這一切都發生在後臺,通常你不會注意到這一點。

另一方面,P3.strlist和P4.strlist是普通的指針,並且始終指向同一個對象。這裏沒有任何自動拷貝。

2

似乎delphi使對象的shallow copy。 淺拷貝意味着所有的本地數據類型都被複制,但是這些對象只能被引用拷貝。

所以在拷貝分配後,兩個對象都持有對同一個strlist對象的引用。

1

將所有值從P3複製到P4

strlst IST只是一個對象TStringList的引用,這參考也被複制,因此P4.strlst指向同一個對象P3.strlst

3

字符串是按需複製。這意味着當您更改複製的字符串時,它將創建更改的字符串的新實例。爲了簡單起見,您可以假定字符串副本是字符串數據的副本。

當您分配一個類實例時,只會複製指向該實例的指針,而不是實例本身。複製後,仍然只有一個類實例。您可以從您的代碼中看到,代碼中只有一個TStringList.Create。

相關問題