13

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? :-)

LU RD
  • 34,438
  • 5
  • 88
  • 296
Wouter van Nifterick
  • 23,603
  • 7
  • 78
  • 122

1 Answers1

16

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.

Community
  • 1
  • 1
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • There are a few reasons why it might be useful to use `Initialize` for local variables: one I've encountered is a managed variable with `absolute` overlaying an unmanaged one. But it's certainly not the right answer for this question, and I'm in full agreement with the rest of your answer. –  Jan 05 '13 at 21:40
  • @hvd That's an extreme edge case. – David Heffernan Jan 05 '13 at 21:43
  • @David I've seen Default(T) generate very inefficient code for records or static arrays with managed types, so as a rule of thumb, don't use Default(T) unless there is no other choice. – Eric Grange Jan 06 '13 at 06:57
  • 1
    The constant assignment has one additional advantage. If there are some values that has to be initialized to a non-default value, it's easy to just declare those values leaving out the necessity to define the default ones. Example: `const cMyVar: TMyVar = (Val1:3);` – LU RD Jan 06 '13 at 09:04
  • 2
    @Eric Can you give an example. – David Heffernan Jan 06 '13 at 09:51