2014-12-02 67 views
3

我有以下代碼:數組類型分配如何工作?

type 
    PSuperListItem = ^TSuperListItem; 
    TSuperListItem = record 
    SubItems : array of String; 
    Marked : Boolean; 
    ImageIndex: Integer; 
    end; 

    TSuperListItems = array of PSuperListItem; 

    TMyList = class(TCustomControl) 
    public 
    Items, ItemsX : TSuperListItems; 
    procedure SwapItemLists; 
    end; 

procedure TMyList.SwapItemLists; 
var tmp:TSuperListItems; 
begin 
tmp:=Items; Items:=ItemsX; ItemsX:=tmp; 
end; 

我想知道,如果我從SwapItemLists做正確的assingtions。當我將Items設置爲tmp時發生了什麼?將會創建一個Items的新副本,或者只傳遞該變量的指針?

回答

8

動態數組是參考類型。這意味着你只需交換引用。數組的內容不會被複制。

能夠自己回答這類問題的關鍵是瞭解成爲參考類型意味着什麼。在動態數組的情況下,動態數組類型的變量保存對數組的引用。這是通過動態數組變量作爲指向數組的指針在幕後實現的。

考慮以下代碼:

var 
    a, b: TArray<Integer>; 
.... 
a := TArray<Integer>.Create(42); 
b := a; 
b[0] := 666; 
Assert(a[0] = 666); 
Assert(@a[0] = @b[0]); 

在這段代碼中,只有過一個陣列。變量ab都指向該數組的相同實例。

爲了製作動態數組的副本,請使用System單元中的Copy函數。

引用類型的其他示例包括類實例變量,接口變量,匿名方法和字符串。除字符串外,這些行爲與動態數組的行爲類似。

字符串實現copy-on-write。這意味着如果一個字符串對象具有多於一個的引用,那麼通過引用進行的修改會在修改點進行復制。這具有使字符串數據類型在語義上像數值類型那樣行爲的效果。實際上,當您使用字符串賦值時,該賦值語義上不可複製。但是,字符串複製的實際實施被推遲到需要時爲止,作爲優化。

+0

也許挑剔,但我認爲你的關於字符串分配的陳述可能會讓將來的讀者感到困惑:你說分配是通過複製字符串來執行的,然後你繼續複製直到需要爲止。所以,未來的讀者可能會懷疑字符串何時被複制。 – iamjoosy 2014-12-02 16:10:49

+0

@iamjoosy公平點。我嘗試了一個重新詞彙。我試圖得到的是,從程序員的角度來看,字符串的行爲就像是值,但實現是與COW的引用。從廣義上說,你不需要知道實現,並且如果你把字符串看作是價值的話,那麼你的心智模型就會匹配行爲。 – 2014-12-02 16:13:33