【问题标题】:Difference between Initialize(), Default() and FillChar()Initialize()、Default() 和 FillChar() 之间的区别
【发布时间】:2013-01-05 20:40:12
【问题描述】:

假设您有一个要初始化的本地记录:

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

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

  WriteLn(Val1,Val2);
end;

除了“手动”设置每个字段之外,还有几种方法可以做到这一点。

  1. 使用初始化():

    Initialize(MyVar);
    
  2. 使用默认():

    MyVar := Default(TMyVar);
    
  3. 使用FillChar

    FillChar(MyVar,SizeOf(MyVar),0);
    
  4. 定义一个空的constant,并将其分配给var

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

以上所有方法似乎都适用于本例这样的情况。我猜你甚至可以定义一个全局变量来初始化它。

但是有没有首选的方法?或者在某些情况下不建议使用上述任何一种,或者它根本不起作用?

简而言之,初始化本地堆栈变量的明确正确方法tm是什么? :-)

【问题讨论】:

    标签: delphi initialization


    【解决方案1】:

    切勿将Initialize 用于局部变量。

    Initialize 只能在 Delphi 代码中使用,其中变量是通过 New 标准过程以外的其他方式动态分配的。

    更重要的是,由于它不包含任何托管类型,因此它会优化为与您的记录一起使用的 nop。所以,我们可以放弃这个选项,将竞争者减少到三个。

    其余三个竞争者对未初始化的局部变量都有相同的效果。但是,在具有托管成员的局部变量上使用 FillChar 是有风险的,例如字符串、接口引用、变体等。如果托管成员已被初始化,那么您将破坏引用计数机制。但是,如果您确定记录尚未初始化,那么FillChar 是安全且高效的,尽管在我看来相当难看。就个人而言,我会拒绝 FillChar 担任这个角色。

    剩下Default(T) 和常量赋值。在旧版本的 Delphi 中,您只能使用常量赋值。公平地说,当您声明常量时,常量赋值与FillChar 一样丑陋。因此,在我看来,在现代 Delphi 版本中,我会选择 Default(),因为它更简洁且可读性更好。

    discussed in a question covering similar ground 一样,当您将Default(T) 分配给变量时,编译器会生成非常高效的代码。

    【讨论】:

    • 对局部变量使用Initialize 可能有用的原因有几个:我遇到的一个是托管变量,absolute 覆盖了一个非托管变量。但这肯定不是这个问题的正确答案,我完全同意你的其他答案。
    • @hvd 这是极端情况。
    • @David 我已经看到 Default(T) 为具有托管类型的记录或静态数组生成非常低效的代码,因此根据经验,除非没有,否则不要使用 Default(T)其他选择。
    • 常量赋值还有一个额外的好处。如果有一些值必须初始化为非默认值,则很容易只声明这些值而无需定义默认值。示例:const cMyVar: TMyVar = (Val1:3);
    • @Eric 你能举个例子吗?
    猜你喜欢
    • 2012-09-03
    • 2015-02-25
    • 2017-01-09
    • 2019-08-20
    • 2016-03-15
    • 2019-04-17
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多