我最近在 Delphi 中發現了一個關于動態陣列的有趣“陷阱”,并且想知道避免該問題的最佳方法。
假設我們有以下示例,其中重用了動態陣列變數:
function FillArray(Count: Integer): TArray<Integer>;
var
i: Integer;
begin
SetLength(result, Count);
for i := 0 to Count - 1 do
result[i] := i;
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var
list: TArray<Integer>;
begin
list := FillArray(5);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := FillArray(8);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := FillArray(12);
meLog.Lines.Add(IntToStr(NativeInt(list)));
end;
由于函式的result變數只是一個隱含var引數,因此list變數正在被重用,并且隨著陣列的后續大小增加,從 5 到 8,然后到 12,然后陣列正在重新分配,因此輸出為:
2138845992
2138930232
2138887416
但是,如果我首先以 12 的大小開始創建:
list := FillArray(12);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := FillArray(8);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := FillArray(5);
meLog.Lines.Add(IntToStr(NativeInt(list)));
然后重復使用相同的動態陣列,因為不需要重新分配,則輸出為:
2138887416
2138887416
2138887416
這是一個令人討厭的“陷阱”,就好像我將每個分配存盤在list其他地方然后我沒有得到唯一的陣列。
這很容易避免,我可以這樣做:
function FillArray(Count: Integer): TArray<Integer>;
var
i: Integer;
begin
result := nil;
SetLength(result, Count);
for i := 0 to Count - 1 do
result[i] := i;
end;
要么
list := nil;
list := FillArray(12);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := nil;
list := FillArray(8);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := nil;
list := FillArray(5);
meLog.Lines.Add(IntToStr(NativeInt(list)));
要么
list := Copy(FillArray(12));
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := Copy(FillArray(8));
meLog.Lines.Add(IntToStr(NativeInt(list)));
list := Copy(FillArray(5));
meLog.Lines.Add(IntToStr(NativeInt(list)));
其中任何一個都會給我一個獨特的陣列。最好的似乎是result := nil,因為您會假設這樣的函式應該回傳一個唯一的陣列。但是設定result := nil,然后做一個setLength看起來是錯誤的,不理解這個問題的人可能會result := nil在未來認為它是多余的。
所以我的問題是,我對此的理解是否正確,是否有更好的方法來創建一個獨特的動態陣列?
uj5u.com熱心網友回復:
“如果我將串列的每個分配存盤在其他地方,那么我不會得到唯一的陣列。”
如果您獲取每個串列的副本,則不會重用該串列,因為動態陣列是參考計數的。
使用以下代碼再次運行您的測驗:
procedure TfrmMain.Button1Click(Sender: TObject);
var
list,
list1,
list2: TArray<Integer>;
begin
list := FillArray(12);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list1 := list;
list := FillArray(8);
meLog.Lines.Add(IntToStr(NativeInt(list)));
list2 := list;
list := FillArray(5);
meLog.Lines.Add(IntToStr(NativeInt(list)));
end;
日志每次都會顯示不同的值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/446164.html
標籤:德尔福
上一篇:如何在Pascal中獲取IP地址
下一篇:創建組件以更新控制元件的全域屬性
