Copy dynamic array

classic Classic list List threaded Threaded
13 messages Options
Reply | Threaded
Open this post in threaded view
|

Copy dynamic array

Torsten Bonde Christiansen
Hi List.

This i a real newbie question:

I hardly use dynamic array, so I don't know if there is a simpler method
to copying a dynamic interger array than the straigh forward method:

(I need a copy to preseve the current values of OldArray, since OldArray
will change values later in the program)

SetLength(NewArray, Length(OldArray));
for i := Low(OldArray) to High(OldArray) do
   NewArray[i] := OldArray[i];


Best regards,
Torsten.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Maciej Izak
2018-05-14 11:46 GMT+02:00 Torsten Bonde Christiansen <[hidden email]>:
SetLength(NewArray, Length(OldArray));
for i := Low(OldArray) to High(OldArray) do
  NewArray[i] := OldArray[i];

you can just use :

NewArray := Copy(OldArray);

looks better ;)

--
Best regards,
Maciej Izak

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Bart-48
On Tue, May 15, 2018 at 12:06 PM, Maciej Izak <[hidden email]> wrote:

> you can just use :
>
> NewArray := Copy(OldArray);

Mind you, if OldArray is an array of array, Copy() will copy the
reference to the "second" array, not the actal data.

var
  a,b: array of array of TSomeType;

SetLength(a, 5, 5);
a[0,0] := VarOfTSomeType;
b := copy(a);
a[0,0] := SecondVarOfTSomeType;
writeln(b[0,0]); //prints SecondVarOfTSomeType.

You would need to do b[i] := copy(a[i]) in a loop to copy the data.

Bart
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

denisgolovan
A side note:

I am still wondering why there is no something like "Clone" function to make an independent copy of string/array/... ? It's used quite often in practice (as we don't have copy-on-write working in all circumstances).

BR,
Denis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Florian Klämpfl
Am 15.05.2018 um 14:15 schrieb denisgolovan:
> A side note:
>
> I am still wondering why there is no something like "Clone" function to make an independent copy of string/array/... ? It's used quite often in practice (as we don't have copy-on-write working in all circumstances).

There is. It is just called copy.

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

denisgolovan
Well.

"Copy" works for arrays only.
Neither strings nor records work.
Tested in pretty old svn rev. 37656

//=================================================
program project1;

{$mode objfpc}{$H+}

type
  TRec = record
    s1:string;
    i1:integer;
  end;

var S1,S2:string;
    A1,A2:array of integer;
    R1,R2:TRec;
begin
  A1:=[1,2,3];
  A2:=Copy(A1);
  A2[0]:=10;
  writeln(A1[0]);
  writeln(A2[0]);

  S1:='123';
  S2:=Copy(S1);

  R1.s1:='123';
  R1.i1:=1;
  R2:=Copy(R1);
end.
//===========================================

BR,
Denis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Alexander Grotewohl
type
   TRec = record
     s1:string;
     i1:integer;
   end;

var
   S1,S2:string;
   R1,R2:TRec;
begin
   S1:='123';
   S2:=S1; // lol

   R1.s1:='123';
   R1.i1:=1;
   move(R1, R2, sizeof(TRec));
   writeln(R2.s1, ' ', R2.i1);
end.


On 5/15/2018 2:39 PM, denisgolovan wrote:

> Well.
>
> "Copy" works for arrays only.
> Neither strings nor records work.
> Tested in pretty old svn rev. 37656
>
> //=================================================
> program project1;
>
> {$mode objfpc}{$H+}
>
> type
>    TRec = record
>      s1:string;
>      i1:integer;
>    end;
>
> var S1,S2:string;
>      A1,A2:array of integer;
>      R1,R2:TRec;
> begin
>    A1:=[1,2,3];
>    A2:=Copy(A1);
>    A2[0]:=10;
>    writeln(A1[0]);
>    writeln(A2[0]);
>
>    S1:='123';
>    S2:=Copy(S1);
>
>    R1.s1:='123';
>    R1.i1:=1;
>    R2:=Copy(R1);
> end.
> //===========================================
>
> BR,
> Denis
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Alexander Grotewohl
I should probably also note that you shouldn't use move with records
that have ansistrings or other dynamically allocated variables in them..


On 5/15/2018 6:49 PM, Alexander Grotewohl wrote:

> type
>   TRec = record
>     s1:string;
>     i1:integer;
>   end;
>
> var
>   S1,S2:string;
>   R1,R2:TRec;
> begin
>   S1:='123';
>   S2:=S1; // lol
>
>   R1.s1:='123';
>   R1.i1:=1;
>   move(R1, R2, sizeof(TRec));
>   writeln(R2.s1, ' ', R2.i1);
> end.
>
>
> On 5/15/2018 2:39 PM, denisgolovan wrote:
>> Well.
>>
>> "Copy" works for arrays only.
>> Neither strings nor records work.
>> Tested in pretty old svn rev. 37656
>>
>> //=================================================
>> program project1;
>>
>> {$mode objfpc}{$H+}
>>
>> type
>>    TRec = record
>>      s1:string;
>>      i1:integer;
>>    end;
>>
>> var S1,S2:string;
>>      A1,A2:array of integer;
>>      R1,R2:TRec;
>> begin
>>    A1:=[1,2,3];
>>    A2:=Copy(A1);
>>    A2[0]:=10;
>>    writeln(A1[0]);
>>    writeln(A2[0]);
>>
>>    S1:='123';
>>    S2:=Copy(S1);
>>
>>    R1.s1:='123';
>>    R1.i1:=1;
>>    R2:=Copy(R1);
>> end.
>> //===========================================
>>
>> BR,
>> Denis
>> _______________________________________________
>> fpc-pascal maillist  -  [hidden email]
>> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
>
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

denisgolovan
Yes.
That's exactly why I gave that example.
Your method with Move will trigger segfault eventually, so the compiler support is required to handle it properly.

BR,
Denis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Michael Van Canneyt


On Wed, 16 May 2018, denisgolovan wrote:

> Yes.
> That's exactly why I gave that example.
> Your method with Move will trigger segfault eventually, so the compiler support is required to handle it properly.

But compiler support for copying records exists.

What's wrong with simply doing
  R2:=R1;
in the given examples ?

Michael.
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

denisgolovan
Doing the same conceptual thing using different syntax does not seem right as generics, macros and other nice stuff become clumsy and too verbose.

See

//========================================================
program project1;
{$mode objfpc}

type
   TRec= record
      A:array of integer;
      S:string;
   end;

var R1,R2:TRec;
begin
   SetLength(R1.A, 3);
   R1.A[0]:=1;
   R1.A[1]:=2;
   R1.A[2]:=3;
   R1.S:='123';

   R2:=R1; // shallow copying <> full clone
   R2.A[0]:=10;
   R2.S[1]:='S';

   // does not work as expected (no copy-on-write/cloning)
   writeln(R1.A[0]); // prints 10
   writeln(R2.A[0]); // prints 10

   // works fine
   writeln(R1.S[1]); // prints 1
   writeln(R2.S[1]); // prints S
end.
//========================================================

BR,
Denis
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

Alexander Grotewohl
What would the expected behavior be for pointers inside records? What if
the record is actually a linked list? Or includes classes and objects?
Do we run the constructor or no? If the record has file handles do we
attempt to recreate their state? (perhaps running assign again, and
crossing our fingers the file hasn't been deleted - which at least on
Linux is definitely possible)

On 05/16/2018 04:24 AM, denisgolovan wrote:

> Doing the same conceptual thing using different syntax does not seem right as generics, macros and other nice stuff become clumsy and too verbose.
>
> See
>
> //========================================================
> program project1;
> {$mode objfpc}
>
> type
>     TRec= record
>        A:array of integer;
>        S:string;
>     end;
>
> var R1,R2:TRec;
> begin
>     SetLength(R1.A, 3);
>     R1.A[0]:=1;
>     R1.A[1]:=2;
>     R1.A[2]:=3;
>     R1.S:='123';
>
>     R2:=R1; // shallow copying <> full clone
>     R2.A[0]:=10;
>     R2.S[1]:='S';
>
>     // does not work as expected (no copy-on-write/cloning)
>     writeln(R1.A[0]); // prints 10
>     writeln(R2.A[0]); // prints 10
>
>     // works fine
>     writeln(R1.S[1]); // prints 1
>     writeln(R2.S[1]); // prints S
> end.
> //========================================================
>
> BR,
> Denis
> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Copy dynamic array

denisgolovan
> What would the expected behavior be for pointers inside records? What if
> the record is actually a linked list? Or includes classes and objects?
> Do we run the constructor or no? If the record has file handles do we
> attempt to recreate their state? (perhaps running assign again, and
> crossing our fingers the file hasn't been deleted - which at least on
> Linux is definitely possible)

Well.
The answer is simple - value types (scalars, strings, records, variants, arrays of mentioned) are good functional citizens.
Cloning is well defined for them as compound value is also value.

Should someone wants for add complexity (read OOP/pointers/classes and other crap) - use http://wiki.freepascal.org/management_operators#Copy at your own risk.

--
Regards,
Denis Golovan
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal