Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2007-10

Arrays of objects

13 messages · 5 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Adrian Maier

Hello,

I'm seeking for advice about which is the best way to hold an array of class instances
I need to access the elements using its position (like a regular array) , and also i'd like
the structure to grow when I add more elements.

Fpc has 'dynamic arrays' , and also there several classes like TFPList, TList
in RTL.Classes . Also, the FCL has the contrns unit which also contains some classes that can be used for storing objects into memory.

At this point there are already too many options, and I am unsure what to use.

The 'dynamic arrays' are very close to what i'm looking for, except that I couldn't
find the documentation page of the SetLength procedure. In particular : what happens if i call this procedure again for the same array : an does it "re-allocate"
memory for the array , or "resizes" its memory ?

Cheers,
Adrian Maier

Reply by email

Matt Emson
to Adrian Maier
Adrian Maier wrote 7 lines
Hello, I'm seeking for advice about which is the best way to hold an array of class instances I need to access the elements using its position (like a regular array) , and also i'd like the structure to grow when I add more elements

TObjectList

If you want specific non type casted code, write a wrapper that exposes the obvious methods and properties:

type
   TMyObject = class
    public
        a: integer;
    end;
    TMyObjectListWrapper = class
    private
       flist: TObjectList;
       procedure SetItem(index: counter; item: TMyObject);
       function GetItem(index: integer): TMyObject;
     public
        function Count: integer;
        function Add(item: TObject): integer;
        procedure Delete(index: integer);
        procedure Clear;
        property Items[index: integer]:TMyObject read GetItem write SetItem;
    end;

untested because I have no Pascal to compile with, but you get the jist.

M

Reply by email

Adrian Maier
to Matt Emson
Matt Emson wrote 9 lines
Adrian Maier wrote: > Hello, > > I'm seeking for advice about which is the best way to hold an array of > class instances > I need to access the elements using its position (like a regular > array) , and also i'd like > the structure to grow when I add more elements TObjectList

I am aware that TObjectList is one of the possible ways. But I was hoping to get a better understanding about the purpose of these various classes or types of array , and more importantly what are the drawbacks .

Is there really no wiki page , tutorial, anything that provides an overview of the collections and types of arrays that FPC has ?

Adrian Maier

Reply by email

Joao Morais
to Adrian Maier
Adrian Maier wrote 18 lines
On 10/31/07, Matt Emson wrote: > Adrian Maier wrote: >> Hello, >> >> I'm seeking for advice about which is the best way to hold an array of >> class instances >> I need to access the elements using its position (like a regular >> array) , and also i'd like >> the structure to grow when I add more elements > TObjectList I am aware that TObjectList is one of the possible ways. But I was hoping to get a better understanding about the purpose of these various classes or types of array , and more importantly what are the drawbacks . Is there really no wiki page , tutorial, anything that provides an overview of the collections and types of arrays that FPC has ?

You can use dynamic arrays, they work like an ansi string:

var
   VArray: array of TSomeClass;
begin
   SetLength(VArray, 10);
   // now you have VArray[0] .. VArray[9];
   SetLength(VArray, 20);
   // now you have [0] .. [19];
   // Length(VArray) = 20
   // for I := 0 to Pred(Length(VArray)) is a valid statement

They are reference counted, just like ansi strings, ie don't worry about memory leakages.

Joao Morais

Reply by email

Marco van de Voort
to Joao Morais
Show quoted text 12 lines
Adrian Maier wrote: VArray: array of TSomeClass; begin SetLength(VArray, 10); // now you have VArray[0] .. VArray[9]; SetLength(VArray, 20); // now you have [0] .. [19]; // Length(VArray) = 20 // for I := 0 to Pred(Length(VArray)) is a valid statement They are reference counted, just like ansi strings, ie don't worry about memory leakages.

... Of the array itself. The objects it contains is another matter.

Reply by email

Adrian Maier
to Joao Morais: You can use dynamic arrays, they work like an ansi string: var VArray: array of…
Joao Morais wrote 34 lines
Adrian Maier wrote: > On 10/31/07, Matt Emson wrote: >> Adrian Maier wrote: >>> Hello, >>> >>> I'm seeking for advice about which is the best way to hold an array of >>> class instances >>> I need to access the elements using its position (like a regular >>> array) , and also i'd like >>> the structure to grow when I add more elements >> TObjectList > > I am aware that TObjectList is one of the possible ways. > But I was hoping to get a better understanding about the purpose of these > various classes or types of array , and more importantly what are the > drawbacks . > > Is there really no wiki page , tutorial, anything that provides an overview of > the collections and types of arrays that FPC has ? You can use dynamic arrays, they work like an ansi string: var VArray: array of TSomeClass; begin SetLength(VArray, 10); // now you have VArray[0] .. VArray[9]; SetLength(VArray, 20); // now you have [0] .. [19]; // Length(VArray) = 20 // for I := 0 to Pred(Length(VArray)) is a valid statement They are reference counted, just like ansi strings, ie don't worry about memory leakages.

The detail that is not crystal clear to me is : after the first SetLength and i set the first 3 elements , is it *guaranteed* that the second SetLength
leaves those first 3 elements untouched ?

That's what i meant by "resize" as opposed to "reallocate" . Reallocation could occur in some other place in memory , leading to loosing the original contents. I have actually tested it with a small program, but since i've been able to access indexes way beyond the allocated number of elements before getting the program killed i want to be sure that i understand the proper use of dynamic arrays.

Thanks Joao !

Adrian Maier

Reply by email

Matt Emson
to Marco van de Voort: ... Of the array itself. The objects it contains is another matter.
Marco van de Voort wrote 15 lines
> Adrian Maier wrote: > VArray: array of TSomeClass; > begin > SetLength(VArray, 10); > // now you have VArray[0] .. VArray[9]; > SetLength(VArray, 20); > // now you have [0] .. [19]; > // Length(VArray) = 20 > // for I := 0 to Pred(Length(VArray)) is a valid statement > > They are reference counted, just like ansi strings, ie don't worry about > memory leakages. > ... Of the array itself. The objects it contains is another matter.

Which is why TObjectList is a good choice: TObjectList.Create(True) makes all instances added to the list owned by the list and free'd when the list is free'd. TObjectList also manages the allocation/deallocation and size for you.

M

Reply by email

Joao Morais
to Marco van de Voort: ... Of the array itself. The objects it contains is another matter.
Marco van de Voort wrote 14 lines
> Adrian Maier wrote: > VArray: array of TSomeClass; > begin > SetLength(VArray, 10); > // now you have VArray[0] .. VArray[9]; > SetLength(VArray, 20); > // now you have [0] .. [19]; > // Length(VArray) = 20 > // for I := 0 to Pred(Length(VArray)) is a valid statement > > They are reference counted, just like ansi strings, ie don't worry about > memory leakages. ... Of the array itself. The objects it contains is another matter.

Ah, yes, forgot to mention this. I usually use dyn arrays to manage objects owned by other lists or objects.

Joao Morais

Reply by email

Joao Morais
to Adrian Maier: The detail that is not crystal clear to me is : after the first SetLength and i set…
Adrian Maier wrote 37 lines
On 10/31/07, Joao Morais wrote: > Adrian Maier wrote: >> On 10/31/07, Matt Emson wrote: >>> Adrian Maier wrote: >>>> Hello, >>>> >>>> I'm seeking for advice about which is the best way to hold an array of >>>> class instances >>>> I need to access the elements using its position (like a regular >>>> array) , and also i'd like >>>> the structure to grow when I add more elements >>> TObjectList >> I am aware that TObjectList is one of the possible ways. >> But I was hoping to get a better understanding about the purpose of these >> various classes or types of array , and more importantly what are the >> drawbacks . >> >> Is there really no wiki page , tutorial, anything that provides an overview of >> the collections and types of arrays that FPC has ? > You can use dynamic arrays, they work like an ansi string: > > var > VArray: array of TSomeClass; > begin > SetLength(VArray, 10); > // now you have VArray[0] .. VArray[9]; > SetLength(VArray, 20); > // now you have [0] .. [19]; > // Length(VArray) = 20 > // for I := 0 to Pred(Length(VArray)) is a valid statement > > They are reference counted, just like ansi strings, ie don't worry about > memory leakages. The detail that is not crystal clear to me is : after the first SetLength and i set the first 3 elements, is it *guaranteed* that the second SetLength leaves those first 3 elements untouched?

I don't use dyn array realocation by myself, but seeing this piece of code I'd assume yes:

procedure TFPList.SetCapacity(NewCapacity: Integer);
begin
   If (NewCapacity < FCount) or (NewCapacity > MaxListSize) then
      Error (SListCapacityError, NewCapacity);
   if NewCapacity = FCapacity then
     exit;
   ReallocMem(FList, SizeOf(Pointer)*NewCapacity);
   FCapacity := NewCapacity;
end;
Joao Morais

Reply by email

Lourival Mendes
to Joao Morais: Ah, yes, forgot to mention this. I usually use dyn arrays to manage objects owned by…

Dear Joao,

I do beleive that the SetLength only resize the array, ie: The Vetor has 3 elements like:

   Vetor[0]:= 1
   Vetor[1]:= 2
   Vetor[2]:= 3
  And then eu want the same variable but with only 2 element, then
   SetLength(Vetor, 2)
   Vetor[0]:= 1
   Vetor[1]:= 2

As you can see you don't lose the first 2, After that you want 4 elements on the same variable:

SetLength(Vetor, 4)

If you print the variable, before associate any value to it you will get:

   Vetor[0]:= 1
   Vetor[1]:= 2
   Vetor[2]:= 0
   Vetor[3]:= 0
  Hope it helped

Lourival

2007/10/31, Joao Morais :

Show quoted text 25 lines
Marco van de Voort wrote: >> Adrian Maier wrote: >> VArray: array of TSomeClass; >> begin >> SetLength(VArray, 10); >> // now you have VArray[0] .. VArray[9]; >> SetLength(VArray, 20); >> // now you have [0] .. [19]; >> // Length(VArray) = 20 >> // for I := 0 to Pred(Length(VArray)) is a valid statement >> >> They are reference counted, just like ansi strings, ie don't worry about >> memory leakages. > > ... Of the array itself. The objects it contains is another matter. Ah, yes, forgot to mention this. I usually use dyn arrays to manage objects owned by other lists or objects. -- Joao Morais _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Lourival J. Mendes Neto

Reply by email

Joao Morais
to Lourival Mendes
Lourival Mendes wrote 15 lines
SetLength(Vetor, 2) Vetor[0]:= 1 Vetor[1]:= 2 As you can see you don't lose the first 2, After that you want 4 elements on the same variable: SetLength(Vetor, 4) If you print the variable, before associate any value to it you will get: Vetor[0]:= 1 Vetor[1]:= 2 Vetor[2]:= 0 Vetor[3]:= 0

I assume the same based on the rtl internals -- except that you cannot assume values from a newly allocated area (except if you are dealing with objects)

Joao Morais

Reply by email

Marco van de Voort
to Adrian Maier: The detail that is not crystal clear to me is : after the first SetLength and i set…
Show quoted text 8 lines
On 10/31/07, Joao Morais wrote: > They are reference counted, just like ansi strings, ie don't worry about > memory leakages. The detail that is not crystal clear to me is : after the first SetLength and i set the first 3 elements , is it *guaranteed* that the second SetLength leaves those first 3 elements untouched ?

Yes. But they can be copied, so address to them might be invalid.

That's what i meant by "resize" as opposed to "reallocate" . Reallocation could occur in some other place in memory , leading to loosing the original contents.

It does resize if possible, reallocate (and copy the original data as far as it fits) else.

Reply by email

Adrian Maier
to Marco van de Voort
Marco van de Voort wrote 17 lines
> On 10/31/07, Joao Morais wrote: > > They are reference counted, just like ansi strings, ie don't worry about > > memory leakages. > > The detail that is not crystal clear to me is : after the first SetLength > and i set the first 3 elements , is it *guaranteed* that the > second SetLength > leaves those first 3 elements untouched ? Yes. But they can be copied, so address to them might be invalid. > That's what i meant by "resize" as opposed to "reallocate" . Reallocation > could occur in some other place in memory , leading to loosing the > original contents. It does resize if possible, reallocate (and copy the original data as far as it fits) else.

Thanks for the info!

Adrian Maier

Reply by email