【问题标题】:Is there way of copying the whole array into another array? (Other than using a For-loop)有没有办法将整个数组复制到另一个数组中? (除了使用 For 循环)
【发布时间】:2022-05-16 16:24:46
【问题描述】:

有没有办法将整个数组复制到另一个数组中?除了使用 for 循环。

movecopy 命令是否适用于此? 我确实尝试过,但它有一个错误:“不兼容的类型”。

我应该坚持使用 for 循环吗?

【问题讨论】:

  • Move 使用 for 循环。至少在 Delphi 7 中是这样。什么代码导致了错误?
  • 我不知道。移动和复制都导致错误。 (虽然我没有同时使用它们)
  • Move 不使用 for 循环。它是用 asm 编写的,即使在 Delphi 7 中,也可以在 Delphi 7 中使用 rep movsd/movsb,或者在较新的 Delphi 版本中使用更快的 FPU 指令。
  • 如果数组的类型相同且大小固定(非动态),那么您只需将一个分配给另一个(array1 := array2)即可复制。
  • 不幸的是,它是一个动态数组。但我会把它归档以备将来参考。谢谢。 :D

标签: delphi


【解决方案1】:

为了安全起见,请在动态数组上使用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)。这会复制整个数组。
  • @Viktor,你可能会和我们的捷克 "MVP" 分享Copy(Source) 技巧,因为他似乎刚刚发现了省略最后一个参数的可能性(真不好意思不小心访问了他们的博客)。
【解决方案2】:

对于动态数组:

var A,B: array of Byte;

begin
  SetLength(A, <size>);
  //initialize A

  B:= A; 
  SetLength(B,Length(A));

end;

在动态数组中,赋值语句只复制对数组的引用,而 SetLength 负责物理复制/复制它,留下两个独立的、独立的动态数组。

【讨论】:

  • 为什么不直接使用:a := Copy(b, 0, MaxInt); ?
【解决方案3】:

article on delphibasics.co.uk

您可以使用 Copy 方法复制数组(传入 0 作为索引,传入 Length(Source) 作为计数以复制全部内容)。

不要对字符串/数组/接口/等托管类型的数组使用 Move 或 CopyMemory。这样做会绕过 Delphi 的引用计数机制,并会导致内存泄漏和数据损坏。

【讨论】:

    【解决方案4】:

    1- 如果你的数组不包含任何字符串或动态数组,你可以使用move,但是动态数组不能像固定大小的数组那样处理:

    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;
    

    【讨论】:

    • "如果你知道自己在做什么,因为 sizeof(A)=40" 是 44。
    【解决方案5】:

    您可以使用使用泛型函数的记录类型将数组复制到动态 TArray 变量,我已经开始使用:

     TGen = record // Unused record to allow generic functions.
     public
          ...
           class function arrayCopy<T>(const a: array of T): TArray<T>; static;
     end;
    
    
    
    class function TGen.arrayCopy<T>(const a: array of T): TArray<T>;
    var i: integer;
    begin
      SetLength(result, length(a));
      for i := Low(a) to High(a) do
        result[i] := a[i];
    end;
    

    给定一个表单变量

    dtls: TArray<TGridSetupDetails>;
    

    以及从枚举类型的数组中分配的参数

    const adtls: array of TGridSetupDetails
    

    你可以初始化表单变量:

      dtls := TGen.arrayCopy<TGridSetupDetails>(adtls);
    

    【讨论】:

    • 这对于大型数组来说会非常慢!
    猜你喜欢
    • 1970-01-01
    • 2018-10-12
    • 1970-01-01
    • 2017-05-14
    • 2015-08-13
    • 2021-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多