Short question about copying array contents and pointer assignment

Considering the following:

TCell = packed record
  status : cell_status;
  to_update : cell_status;
  lifetime: word;
  resist: byte;
  activated: boolean;
end;

type cell_pointer = ^TCell;

TMargolusBlock = packed record
  cell : array[0..3] of cell_pointer;
end;

TMargolusArray = class(TObject)
  mblock : array of array of TMargolusBlock;
  constructor create(size : Integer);
  destructor Destroy;
    override;
end;


currentMargolusArray : TMargolusArray;


Then:

currentMargolusArray := MargolusArrayA;

doesn't work, I just get a TMargolusArray object with an array filles with nils.
How can I get the contents of MargolusArrayA in currentMargolusArray ? Or do I really need to copy the whole thing?
(like: for teller := 0 to ...: currentMargolusArray.cell[0] := MargolusArrayA.cell[0] etc..)

Furthermore, a bit related, what is the difference between:

type cell_pointer = ^TCell;
cpointer : cell_pointer;
cell : Tcell;

cpointer := @cell;

and

cpointer^ := cell;??
reynaerdeAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LRHGuyCommented:
You just cannot simply "copy" an object.

But you can create a method to do so!

procedure tMargolusArray.CopyFrom(aOrig:tMargolusArray);
begin
  SetLength(MBlock,aOrig.dimension1,aOrig,dimension2);  // get array size from original object
  Move(aOrig.MBlock,MBlock,sizeof(aOrig.MBlock)); // copy array
end;

This puts the address of cell into cpointer:

cpointer := @cell;

This puts the contents of cell into the tcell referenced by cpointer:

cpointer^ := cell;??
0
Wim ten BrinkSelf-employed developerCommented:
The only way: (Not tested in compiler)

var
  I:Integer;
begin
  SetLength(Target, Length(Source));
  for I := Low(Source) to High(Source) do Target[I] := Source[I];
end;

And if the array contains pointers to objects or records, then those things aren't copied either, just the references.

The thing you have to keep in mind is the difference between the actual data and references to data. For a better performance, you should just keep copying those references. Because copying data costs a little bit of time and the more data you have to copy, the more performance you'll lose. Do you really need to copy those arrays?
0
Wim ten BrinkSelf-employed developerCommented:
cpointer := @cell;
Here, cpointer is told to point to a reference pointer that is pointing at cell.

cpointer^ := cell;
Here, the reference that cpointer is pointing to is changed to reference to cell.

Pointers to pointers can make life real complicated. :-)
0
LRHGuyCommented:
What Workshop_Alex indicates is true...if TCell is an object...but in your example, tcell is a record, so be careful!

type
  tcell=record  
  cellptr=^tcell   // pointer to a record

var
  cell:tcell;  //the actual record
  cp:cellptr;

  cp:=@tcell  //cp points to actual record
 
type
  tcell=class
  cellptr=^tcell   //pointer to a pointer

var
  cell:tcell;  //pointer to class object
  cp:cellptr;

  cp:=@tcell; //cp points to a pointer that points to the actual object data

As Workshop said, it can be complicated!
 
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Slick812Commented:
hi again, , first I wonder about having a Record with only ONE elements as your -

TMargolusBlock = packed record
  cell : array[0..3] of cell_pointer;
end;

 this seems kind of "not needed" to me, since a Record was made to hold more then ONE element, so I changed it to a type -

type
  cellMB = array[0..3] of cell_pointer;

I also wondered why you always want to use a pointer to something instead of the something that is pointed to, you use a "cell_pointer" instead of a "TCell", but for me, it seems this would not have any advantage, and would just mean I would have to write more code to initialize and free this cell_pointer, so I changed it to a TCell -

type
  cellMB = array[0..3] of TCell;

  TMargolusArray = class
    FSize: Integer;
    mblock : array of array of CellMB;
    procedure Assign(MArray: TMargolusArray);
    constructor create(size: Integer);
    destructor Destroy; override;
  end;

 - - - - - - - -  - - - -  - - -

I also had to change the class  TMargolusArray , as seen above

 - - - - - - - - - - - - - - - -  - - - -

for your
currentMargolusArray := MargolusArrayA;
doesn't work question. . .

when you use the
 :=
with a TObject, it DOES NOT  create a new TObject, the  currentMargolusArray  will be one and the same as  MargolusArrayA, (the object pointer value is ALL that is copied, no object elements are involved), ,  if you free one of them the other is also gone (because the other is the same thing), as in the code below -



procedure TForm1.sbut_ObjectAsgnClick(Sender: TObject);
var
MArray1, curMArray: TMargolusArray;
begin
MArray1 := TMargolusArray.Create(6);
Marray1.mBlock[5,5,3].lifetime := 12345;
curMArray := MArray1;
// the line above does not create a separate TMargolusArray
// it just copy the Object Pointer, so now they are the same TMargolusArray
ShowMessage(IntToStr(curMArray.mBlock[5,5,3].lifetime));
FreeAndNil(MArray1); // this also frees the curMArray, since they are the same
ShowMessage(IntToStr(curMArray.mBlock[5,5,3].lifetime));
// I get an access violation in the line above
end;


 - - - - - - -  - - - - -  - - - - - -

and Yes, you will really need to copy every array element from one to the  other, here is my code for the  TMargolusArray  , I have added an Assign procedure -

constructor TMargolusArray.create(size: Integer);
begin
FSize := size;
SetLength(mblock, Size, Size);
mblock[0,0,0].status := H; // just for looks, not know your initialize
end;

destructor TMargolusArray.Destroy;
begin
SetLength(mblock, 0,0);
end;

procedure TMargolusArray.Assign(MArray: TMargolusArray);
var
i, j, k: Integer;
begin
if (not Assigned(MArray)) then Exit;
FSize := MArray.FSize;
SetLength(mblock, FSize, FSize);

for i := 0 to FSize-1 do
  for j := 0 to FSize-1 do
    for k := 0 to 3 do
      mblock[i,j,k] := MArray.mblock[i,j,k];
end;

the Assign method is in to the TPersistent Class and not in the TObject class, but I have added it here.
below is some button click code for this -


procedure TForm1.sbut_ObjectAsgnClick(Sender: TObject);
var
MArray1, curMArray: TMargolusArray;
begin
MArray1 := TMargolusArray.Create(6);
Marray1.mBlock[5,5,3].lifetime := 12345;
curMArray := TMargolusArray.Create(Marray1.FSize);
ShowMessage(IntToStr(curMArray.mBlock[5,5,3].lifetime));
curMArray.Assign(MArray1);
FreeAndNil(MArray1);
ShowMessage(IntToStr(curMArray.mBlock[5,5,3].lifetime));
// show the same number in the Marray1
FreeAndNil(curMArray);
end;


- - - - - - - - - - - - - - - - - -  - - - -  - - - - -
maybe some ides from this
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.