有沒有辦法將整個數組複製到另一個數組?除了使用for循環。有沒有辦法將整個數組複製到另一個數組中? (除了使用For循環)
move或copy命令是否適用於此? 我確實嘗試過,但它有一個錯誤:「不兼容的類型」。
我應該堅持for循環嗎?
有沒有辦法將整個數組複製到另一個數組?除了使用for循環。有沒有辦法將整個數組複製到另一個數組中? (除了使用For循環)
move或copy命令是否適用於此? 我確實嘗試過,但它有一個錯誤:「不兼容的類型」。
我應該堅持for循環嗎?
爲了安全起見,在使用動態數組的Copy
功能,因爲它在內部處理的管理類型。
var
a, b: array of string;
或由定義自定義陣列型:
type
TStringArray = array of string;
var
a: TStringArray;
//...and somewhere else
var
b: TStringArray;
然後可以這樣做:在陣列必須是相同的類型,在同一個表達即聲明
a := Copy(b, Low(b), Length(b)); //really clean, but unnecessary
//...or
a := Copy(b, 0, MaxInt); //dynamic arrays always have zero low bound
//and Copy copies only "up to" Count items
你將不得不在靜態數組上使用循環,並在混合數組類型時使用循環(不是我推薦的做法)。
如果你確實需要使用Move
,記得檢查零長度,因爲A[0]
構造可能會引發範圍檢查錯誤(除了編譯器魔術處理並且從未實際執行的SizeOf(A[0])
之外)。
也從來沒有假設A = A[0]
或SizeOf(A) = Length(A) * SizeOf(A[0])
,因爲這隻適用於靜態數組,它會咬死你真的很糟糕,如果你以後嘗試重構巨大的代碼庫動態數組。
儘管使用像0和'MaxInt'這樣硬編碼的上下界很方便,但完全省略邊界更加方便:'a:= Copy(b)'。這複製整個陣列。 – 2013-10-02 02:55:12
@Viktor,你可能會與我們的Czech *「MVP」*共享'Copy(Source)'技巧,因爲他似乎只是發現了遺漏最後一個參數的可能性(對我不小心訪問他們的博客感到羞恥)。 – TLama 2015-06-12 18:26:33
嗯......調用RtlMoveMemory API .... 但是,這是一個for循環確... OK.let的希望,它已經通過SIMD指令...... 或ASM並呼籲SIMD指令優化自己..
移動或複製不起作用,您可以使用CopyMemory,但這需要數組是一個連續的內存塊。
SetLength(DestArray, Length(MyArray));
CopyMemory(@DestArray[0], @MyArray[0], Length(MyArray) * SizeOf(ArrayElement));
如果數組包含指向託管類型(字符串,其他動態數組,接口引用等等)的指針,則refcounts不會**遞增。 – 2010-08-23 08:23:20
你的意思是「移動將不會_always_工作」。它只是將一堆字節從內存中的一個位置複製到另一個位置。只要數組佔用連續的內存塊,就可以移動數組。 – 2010-08-23 08:23:59
Move和CopyMemory是相同的(在函數中 - 唯一的區別是CopyMemory接受指針作爲參數,而Move接受變量(取消引用的指針))。 – 2010-08-23 11:21:22
參見article on delphibasics.co.uk
可以使用複製方法(傳遞0的索引和長度(源)作爲計數複製全部內容)複製的陣列。
不要使用Move或CopyMemory作爲字符串/數組/接口/ etc託管類型的數組。這樣做會繞過Delphi的ref-counting機制,並會導致內存泄漏和數據損壞。
1-如果陣列中不包含任何字符串或動態數組,你可以使用移動,但動態數組不被處理的類似固定大小的數組:如果陣列
var A,B: array[0..10] of integer;
DA, DB: array of double;
i: integer;
begin
for i := low(A) to high(A) do
A[i] := i;
move(A[0],B[0],length(A)*sizeof(A[0])); // first version, compiler does the stuff
move(A[0],B[0],sizeof(A)); // it works
move(A[0],B[0],40); // if you know what you're doing, since sizeof(A)=40
SetLength(DA,10); // DA[0]..DA[9]
for i := 0 to high(DA) do // or for i := 0 to 9 if you know what you're doing
DA[i] :=
SetLength(DB,length(DA));
if length(DA)<=length(DB) then // if your dynamic array may be void, use this before to avoid GPF
move(DA[0],DB[0],length(DA)*sizeof(DA[0]));
if pointer(DA)<>nil then // this will just check that DA[] is not void
move(pointer(DA)^,pointer(DB)^,length(DA)*sizeof(double)); // similar to previous
end;
2-包含字符串或其他參考內容數組,你必須使用一個循環:
var A,B: array[0..10] of string;
i: integer;
begin
for i := 0 to high(A) do
A[i] := IntToStr(i);
for i := 0 to high(A) do
B[i] := A[i]; // this doesn't copy the string content, just add a reference count to every A[], and copy a pointer: it's very fast indeed
end;
對於動態數組:
var A,B: array of Byte;
begin
SetLength(A, <size>);
//initialize A
B:= A;
SetLength(B,Length(A));
end;
在動態陣列中,賦值語句重複僅參考陣列,而SetLength確實物理複製/複製它,留下兩個單獨的,獨立的動態陣列的工作。
Move使用for循環。至少它在Delphi 7中做過。什麼代碼導致了錯誤? – 2010-08-23 08:22:18
我不知道。移動並複製兩者都會導致錯誤。 (雖然我沒有在同一時間使用它們) – Dian 2010-08-23 09:19:37
移動不使用for循環。它是用asm編寫的,即使在Delphi 7中,也可以在Delphi 7中使用rep movsd/movsb,或者在更新的Delphi版本中使用更快的FPU指令。 – 2010-08-23 09:41:34