Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I need to setLength a dynamic array on initialization?

type Tmyclass = class(TObject)
  somearray: array of TSometype
  FBool: Boolean;
  Fint: Integer;
  Fstr: string;
  constructor Create;
  destructor Destroy; override;
end;

implementation

constructor Tmyclass.Create;
begin
  inherited;
  SetLength(somearray,0); //is this needed?
end;

destructor TmyClass.Destroy;
begin
  SetLength(somearray,0); //this IS needed!
  inherited;
end;

Also what types are initialized on creation? For example what I declared in the class. is FBool guranteed to be false? is FInt guranteed to be 0? is Fstr guranteed to be ''?

What about local? Only strings?

I use Delphi XE.

like image 409
pop32 Avatar asked Nov 28 '22 00:11

pop32


2 Answers

All the memory belonging to objects are initialized to 0 on object construction (heap allocation), so usually you don't need to initialize anything belonging to a class, default values (zero memory) are:

  • strings will be ''
  • integers will be 0
  • floating point variables will be 0
  • boolean will be false
  • pointers and object references will be nil
  • dynamic arrays will contain zero elements.

and so on.

For local variables and anything related to stack, it will contain garbage, so you're responsible to provide a meaningful value before using the variables.

Something like:

procedure Something;
var
  x: Integer;
begin
  ShowMessage(IntToStr(X));
end;

will show a random value.

like image 180
jachguate Avatar answered Dec 28 '22 08:12

jachguate


Dynamic arrays are managed types and so are always initialized to nil, equivalent to SetLength(..., 0). You never need to do this.

The only time you can get caught out is when you are returning a dynamic array from a procedure as a function return value. In fact a function return value is in fact just an implicit var parameter.

Consider the following code:

function Foo: string;
begin
  Result := Result + 'X';
end;

var
  i: Integer;

begin
  for i := 1 to 5 do
    Writeln(Foo);
  Writeln(Foo);
  Writeln(Foo);
end;

Output

X
XX
XXX
XXXX
XXXXX
X
X

What's going on here is that the compiler, as an optimization is electing not to re-initialize the implicit local variable inside the loop.

This can catch you out from time to time so I recommend setting to nil return values that are dynamic arrays, strings, interfaces etc. You don't need to do so for class members and it's more idiomatic to let the constructor zero-initialise them automatically.

like image 21
David Heffernan Avatar answered Dec 28 '22 07:12

David Heffernan