在我的Delphi Rio应用程序中,我使用了很多2维动态数组。为了加快某些操作,我想使用move命令而不是copy。我可以使它适用于一维动态数组,但是对于2D或更高版本,我不能。对于第二维,在发出move(A,B,size)之后,数组B的元素指向数组A的元素的相同内存地址,即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
,这与您在your previous question中犯的错误完全相同。
实际上,如果仅删除该行代码,它应该可以工作。注意:我没有详细检查,因此可能还有其他缺陷。
您的代码确实非常复杂,很难看到正在发生什么。至少您的某些问题是由于您的代码过于混乱所致。尝试停止将大量代码放入单个过程中。将代码分成较小的部分,然后在驱动程序例程中将这些较小的部分粘合在一起。
您想使用这样的功能:
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
视为多维数组。不是。它只是一个数组。这是一个数组,其元素又是数组。从技术上讲,它是一个锯齿状的数组。但是,您只需要将其视为一维数组即可。
因此,用于克隆它的功能的操作如下:
与您上一个问题的过程完全相同。那里我们有一个记录数组,并带有一个克隆记录的函数。但是,因为我们已经将克隆外部数组的任务与克隆数组的元素分开了,所以结果代码基本相同。
现在假设您有一个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;
猜猜是什么,和以前完全一样的代码!