Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Initialize(), Default() and FillChar()

Let's say you have a local record that you'd like to initialize:

type 
  TMyRec=record
    Val1, Val2:Integer;
  end;

procedure MyProc;
var
  MyVar:TMyRec;
begin
  // ... ?

  WriteLn(Val1,Val2);
end;

Besides setting each field "manually", there are several ways to do it.

  1. Use Initialize():

    Initialize(MyVar);
    
  2. Use Default():

    MyVar := Default(TMyVar);
    
  3. Use FillChar:

    FillChar(MyVar,SizeOf(MyVar),0);
    
  4. Define an empty constant, and assign that to the var

    const cMyVar:TMyVar=();  
    ...    
    MyVar := cMyVar;    
    

The above all seem to work in situations like this example. I guess you could even define a global variable to get it initialized.

But is there a preferred method? Or are there certain situations where it's not recommended to use any of the above, or where it simply won't work?

To put it short, what's the definitive Right Waytm to initialize a local stack variable? :-)

like image 556
Wouter van Nifterick Avatar asked Jan 05 '13 20:01

Wouter van Nifterick


1 Answers

Never use Initialize for local variables.

Initialize should be used only in Delphi code where a variable is dynamically allocated by other means than the New standard procedure.

What's more it would be optimized to a nop with your record since it doesn't contain any managed types. So, we can throw this option away and reduce the field to three contenders.

The remaining three contenders all have the same effect for an uninitialized local variable. However, it's risky to use FillChar on a local variable with managed members, e.g. strings, interface references, variants etc. If the managed members have been initialized then you will break the reference counting mechanism. However, if you are sure that the record has not been initialized, then FillChar is safe and efficient, albeit rather ugly looking in my view. Personally, I would reject FillChar for this role.

That leaves Default(T) and the constant assignment. In older versions of Delphi you can only use the constant assignment. It's fair to say that the constant assignment is as ugly as FillChar, by the time you've declared the constant. So, in modern Delphi versions I would opt for Default() since it is more concise and reads better, in my view.

As was discussed in a question covering similar ground, the compiler produces very efficient code when you assign Default(T) to a variable.

like image 198
David Heffernan Avatar answered Oct 19 '22 04:10

David Heffernan