Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How should I allocate space for a list of items when I don't know in advance how many I'm going to have?

Tags:

delphi

In another question, David Heffernan posted a comment about his "all time least favourite Delphi construct":

SetLength(FItems, Length(FItems)+1);

The construct he dislikes was heavily used in the Pebongo project, such as in this excerpt:

procedure TBSONDocument.ReadStream( F: TStream ); 
var 
  len : integer; 
  elmtype : byte; 
  elmname : string; 
begin 
  Clear; 
  f.Read( len, sizeof( len ) ); 
  f.Read( elmtype, sizeof( byte ) ); 

  while elmtype <> BSON_EOF do // Loop
  begin 
    elmname := _ReadString( f ); 
    SetLength( FItems, length( FItems ) + 1 ); // This, spotted by TOndrej
    case elmtype of 
      BSON_ARRAY: FItems[high( FItems )] := TBSONArrayItem.Create; 
      BSON_BINARY: FItems[high( FItems )] := TBSONBinaryItem.Create; 
      ...
    end; 
    f.Read( elmtype, sizeof( byte ) ); 
  end; 
end; 

What are the alternatives?

like image 419
menjaraz Avatar asked Dec 07 '11 08:12

menjaraz


People also ask

How do I dynamically allocate memory?

This is known as dynamic memory allocation in C programming. To allocate memory dynamically, library functions are malloc() , calloc() , realloc() and free() are used. These functions are defined in the <stdlib. h> header file.

How do you allocate space in an array?

To allocate memory for an array, just multiply the size of each array element by the array dimension. For example: pw = malloc(10 * sizeof(widget)); assigns pw the address of the first widget in storage allocated for an array of 10 widget s.

Is stack or heap faster?

Because the data is added and removed in a last-in-first-out manner, stack-based memory allocation is very simple and typically much faster than heap-based memory allocation (also known as dynamic memory allocation) e.g. C's malloc .

How do you allocate space in a string?

Space is allocated by calling malloc with the number of bytes needed (for strings this is always one more than the maximum length of the string to be stored): char *pc = malloc(MAXSTR + 1) ; // can hold a string of up to MAXSTR characters.


1 Answers

It's not the SetLength() itself that is bad but incrementing the length in the loop. Example of bad code:

SetLength( Result.FItems, 0 ); 

for i := 0 to high( FItems ) do 
begin 
  SetLength(Result.FItems, Length(Result.Fitems)+1);
  Result.FItems[i] := FItems[i].Clone; 
end; 

In this case array is rearranged and reallocating memory on each iteration. Your posted example doesn't show bad usage of SetLength()

like image 76
Linas Avatar answered Sep 18 '22 23:09

Linas