tags:

views:

178

answers:

5

Is there way of copying the whole array into another array? Other than using a for-loop.

Does the move or copy command work for this? I did try but it had an error: "Incompatible types".

Should I stick to the for-loop?

A: 

hmm...call RtlMoveMemory API.... But that's a for-loop indeed... OK.let's hope it's already optimized by SIMD instructions... or ASM and call SIMD instructions yourself...

A: 

Move or Copy will not work, you could use CopyMemory but this requires that the array is a contigious memory block.

SetLength(DestArray, Length(MyArray));
CopyMemory(@DestArray[0], @MyArray[0], Length(MyArray) * SizeOf(ArrayElement));
Remko
And if the array contains pointers to managed types (strings, other dynamic arrays, interface references, ...), the refcounts will **not** be incremented.
Marjan Venema
You mean "Move won't _always_ work". It just copies a bunch of bytes from one position in memory to another. That can move an array just fine, provided the array occupies a contiguous block of memory.
Frank Shearar
Move and CopyMemory are identical (in function -- the only difference is that CopyMemory accepts pointers as arguments, whereas Move accepts variables (dereferenced pointers)).
Andreas Rejbrand
+4  A: 

See article on delphibasics.co.uk

You can copy an array using Copy method (pass in 0 for the index and Length(Source) as count to copy the full contents).

Do NOT use Move or CopyMemory for arrays of string/array/interface/etc managed types. Doing so will bypass Delphi's ref-counting mechanics and will result in memory leaks and corrupted data.

alex
+1  A: 

1- If your array doesn't contain any string or dynamic array, you can use move, but dynamic arrays are not to be handled like fixed-sized arrays:

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- If your array contains strings or other reference content array, you have to use a loop:

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;
A.Bouchez
+1  A: 

To be on the safe side, use the Copy function on dynamic arrays, as it handles the managed types internally. The arrays must be of the same type, i.e. declared in the same expression:

var  
    a, b: array of string;

or by defining a custom array type:

type   
    TStringArray = array of string;  
var 
    a: TStringArray;  
//...and somewhere else
var  
    b: TStringArray;  

then you can do:

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  

You'll have to use a loop on static arrays and when mixing array types (not that I'd recommend doing it).
If you really have to use Move, remember checking for zero-length, as the A[0] constructs can raise range checking errors, (with the notable exception of SizeOf(A[0]), which is handled by compiler magic and never actually executes).
Also never assume that A = A[0] or SizeOf(A) = Length(A) * SizeOf(A[0]), as this is true only for static arrays and it will bite you really badly if you later try to refactor huge codebase to dynamic arrays.

Viktor Svub