Solved

Short question about copying array contents and pointer assignment

Posted on 2004-10-26
166 Views
Last Modified: 2010-04-05
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;??
0
Question by:reynaerde
    5 Comments
     
    LVL 7

    Assisted Solution

    by:LRHGuy
    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
     
    LVL 17

    Expert Comment

    by:Wim ten Brink
    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
     
    LVL 17

    Expert Comment

    by:Wim ten Brink
    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
     
    LVL 7

    Accepted Solution

    by:
    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
     
    LVL 33

    Assisted Solution

    by:Slick812
    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

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    What Should I Do With This Threat Intelligence?

    Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

    Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
    Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
    This video Micro Tutorial is the first in a two-part series that shows how to create and use custom scanning profiles in Nuance's PaperPort 14.5 (http://www.experts-exchange.com/articles/17490/). But the ability to create custom scanning profiles al…
    This video discusses moving either the default database or any database to a new volume.

    913 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    17 Experts available now in Live!

    Get 1:1 Help Now