[英]How to use move on 2-Dimension Dynamic Arrays of integer/real?
在我的 Delphi Rio 應用程序中,我使用了很多二維動態 Arrays。 為了加快某些操作,我想使用移動命令而不是復制。 我可以使它適用於一維動態 arrays,但對於 2D 或更高版本我不能。 對於第二維,發出 move(A,B,size) 后,數組 B 的元素指向數組 A 元素的相同 memory 地址,即 B 引用 A。實際上我想與 A 分開使用 B。請參閱我的代碼:
program ProjArrayMove;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
Type
Arrayint = Tarray<Integer>;
Arrayreal = TArray<Real>;
MatrixInt = Array of Arrayreal;
var
vectorA, vectorB : Arrayint;
matA, matB : MatrixInt;
idx,idy : integer;
begin
TRY
// =============== TESTING WITH 1D DYNAMIC ARRAYS OF SIMPLE TYPES ==================
Writeln('==============================================================');
Writeln('========= TESTING 1-DIMENSION DYNAMIC ARAYS ==================');
Writeln('===============================================================');
readln;
Writeln('------- Fills Vector A ----------------------------');
SetLength(vectorA,5);
for idx :=0 to 4 do
begin
vectorA[idx] := (idx+1) * 10;
Writeln('VectorA : [' + idx.tostring + '] ' +
Format('Address : %p [%d]' ,[PPointer(@VectorA), VectorA[idx] ]) );
end;
readln;
Writeln('--------------------------------------------------');
Writeln('------ Moves VectorA to VectorB ------------------');
SetLength(VectorB,Length(vectorA));
Move(VectorA[0],VectorB[0],SizeoF(VectorA[0]) * Length(VectorA));
for idx :=0 to 4 do
Writeln('VectorB : [' + idx.tostring + '] ' +
Format('Address : %p [%d]' ,[PPointer(@VectorB), VectorB[idx] ]) );
readln;
Writeln('---------------------------------------------------');
Writeln('------ Changes VectorB contents ------------------');
for idx :=0 to 4 do
begin
vectorB[idx] := (idx+1) * 200;
Writeln('VectorB : [' + idx.tostring + '] ' +
Format('Address : %p [%d]' ,[PPointer(@VectorB), VectorB[idx] ]) );
end;
readln;
Writeln('--------------------------------------------------');
Writeln('------ Checking Vector A ------------------------');
for idx :=0 to 4 do
Writeln('VectorA : [' + idx.tostring + '] ' +
Format('Address : %p [%d]' ,[PPointer(@VectorA), VectorA[idx] ]) );
Writeln;
Writeln('CONCLUSION : ===>> MOVE command works fine for 1-Dimension Dynamic Arrays!');
readln;
//=========================== TESTING WITH MATRIX 2D DYNAMIC ARRAYS OF SIMPLE TYPES ==================
Writeln('===============================================================');
Writeln('========= TESTING 2-DIMENSIONS DYNAMIC ARAYS ==================');
Writeln('===============================================================');
readln;
Writeln('------ Fills MatrixA -----------------------------');
SetLength(matA,5,2);
for idx :=0 to 4 do
for idy := 0 to 1 do
begin
matA[idx][idy] := (idx +1) * (idy +1);
Writeln('Mat A : [' + idx.tostring + '][' + idy.tostring +'] ' +
Format('Address : %p [%f]' ,[PPointer(@matA[idx][idy]), matA[idx][idy] ] ));
end;
readln;
Writeln('-------------------------------------------------');
Writeln('------ Move MatrixA to MatrixB ------------------');
SetLength(matB,length(matA));
//move(matA[0],MatB[0],Sizeof(matA[0]) * length(matA));
move(matA,MatB,Sizeof(matA[0]) * length(matA));
for idx :=0 to 4 do
begin
Setlength(MatB[idx],length(matA[idx]));
//Move(matA[idx][0],matB[idx][0],sizeof(matB[idx][0]) * length(matB[idx]) );
Move(matA[idx],matB[idx],sizeof(matB[idx][0]) * length(matB[idx]) );
for idy := 0 to 1 do
begin
Writeln('Mat B : [' + idx.tostring + '][' + idy.tostring +'] ' +
Format('Address : %p [%f]' ,[PPointer(@matB[idx][idy]), matB[idx][idy] ] ));
end;
end;
readln;
Writeln('-------------------------------------------------');
Writeln('------ Change MatrixB content ------------------');
readln;
for idx :=0 to 4 do
for idy := 0 to 1 do
begin
matB[idx][idy] := 100.5 * (idx+1) * (idy +1);
Writeln('Mat B : [' + idx.tostring + '][' + idy.tostring +'] ' +
Format('Address : %p [%f]' ,[PPointer(@matB[idx][idy]), matB[idx][idy] ] ));
end;
Writeln('-------------------------------------------------');
Writeln('------ Checking Matrix A ------------------------');
readln;
for idx :=0 to 4 do
for idy := 0 to 1 do
Writeln('Mat A : [' + idx.tostring + '][' + idy.tostring +'] ' +
Format('Address : %p [%f]' ,[PPointer(@matA[idx][idy]), matA[idx][idy] ] ));
Writeln;
Writeln('CONCLUSION : ===>> MOVE command DOES NOT WORK on 2-Dimensions Dynamic Arrays!');
readln;
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
readln;
end;
end;
end.
第二維的移動命令是否有問題或遺漏?
謝謝 !
您的問題從這里開始:
Move(matA, matB, Sizeof(matA[0]) * Length(matA));
您正在將動態數組傳遞給Move
。 動態數組被實現為指向數組第一個元素的指針。 因此,您正在覆蓋指針。
也許你想做這樣的事情:
Move(matA[0], matB[0], Sizeof(matA[0]) * Length(matA));
但你也不想這樣做。 那是在托管類型上使用Move
,這與您在上一個問題中所犯的錯誤完全相同。
事實上,如果你只是刪除那行代碼,它應該可以工作。 注意我沒有仔細檢查,所以可能還有其他缺陷。
您的代碼確實非常復雜,很難看到發生了什么。 至少你的一些問題是由於你的代碼被混淆了。 嘗試停止將大量代碼放入單個過程中。 將代碼拆分成更小的部分,然后在驅動程序中將這些更小的部分粘合在一起。
您想像這樣使用 function :
function CloneMatrixInt(const matrix: array of ArrayInt): MatrixInt;
var
i: Integer;
begin
SetLength(Result, Length(matrix));
for i := 0 to High(Result) do
Result[i] := Copy(matrix[i]);
end;
請注意,這與您上一個問題的答案基本相同。 這是為什么?
您需要停止將MatrixInt
視為多維數組。 它不是。 這只是一個數組。 這是一個數組,其元素又是 arrays。 從技術上講,它是一個鋸齒狀陣列。 但是您只需要將其視為一維數組。
所以克隆它的function操作如下:
這與您上一個問題的過程完全相同。 在那里,我們有一個帶有 function 的記錄數組來克隆該記錄。 但是因為我們將克隆外部數組和克隆數組元素這兩個任務分開,所以生成的代碼本質上是相同的。
現在想象你有一個MatrixInt
數組。 比方說
type
ArrayMatrixInt = array of MatrixInt;
好吧,像這樣克隆它:
function CloneArrayMatrixInt(const arrayMatrix: array of MatrixInt): ArrayMatrixInt;
var
i: Integer;
begin
SetLength(Result, Length(arrayMatrix));
for i := 0 to High(Result) do
Result[i] := CloneMatrixInt(matrix[i]);
end;
猜猜看,和以前完全相同的代碼!
鑒於這個問題以及您之前的問題,我能否建議您不要嘗試使用Move
來解決所有問題。 沒有理由建議您遇到的任何問題都可以通過使用Move
來解決。
最后一點。 鋸齒狀 arrays 的分配成本很高,因為它們需要多次分配。 它們的操作效率也很低,因為它們不是連續存儲的。 Delphi 缺少多維數組類型,如果需要極致性能,那么最好實現多維數組類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.