簡體   English   中英

如何在整數/實數的二維動態 Arrays 上使用移動?

[英]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操作如下:

  1. 分配目標數組。
  2. 循環目標數組,從源數組中克隆每個元素。

這與您上一個問題的過程完全相同。 在那里,我們有一個帶有 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM