delphi变量是否默认使用值初始化?

MB.*_*MB. 101 delphi variables initialization

我是Delphi的新手,我一直在运行一些测试来查看默认情况下初始化了哪些对象变量和堆栈变量:

TInstanceVariables = class
  fBoolean: boolean; // always starts off as false
  fInteger: integer; // always starts off as zero
  fObject: TObject; // always starts off as nil
end;
Run Code Online (Sandbox Code Playgroud)

这是我习惯使用其他语言的行为,但我想知道在Delphi中依赖它是否安全?例如,我想知道它是否可能依赖于编译器设置,或者可能在不同的机器上以不同的方式工作.依赖于对象的默认初始化值是正常的,还是在构造函数中显式设置所有实例变量?

至于堆栈(过程级)变量,我的测试显示单位化布尔值为真,单位化整数为2129993264,未初始化对象只是无效指针(即不是nil).我猜测规范是在访问它们之前始终设置过程级变量?

Gia*_*sti 103

是的,这是记录在案的行为:

  • 对象字段始终初始化为0,0.0,'',False,nil或任何适用的值.

  • 全局变量也始终初始化为0等;

  • 本地引用计数*变量始终初始化为nil或'';

  • 本地非引用计数*变量未初始化,因此您必须先分配一个值才能使用它们.

我记得Barry Kelly某个地方为"引用计数"写了一个定义,但是找不到它,所以这应该在此期间做:

reference-counting ==自行引用计数,或直接或间接包含引用计数的字段(用于记录)或元素(用于数组):string, variant, interface 或包含此类型的动态数组静态数组.

笔记:

  • record 本身不足以成为参考计数
  • 我还没有尝试使用泛型

  • @WimtenBrink我觉得你错了.初始化不是在`TObject.Create`中完成的,这是一个void方法,但是在`class function TObject.InitInstance(Instance:Pointer):TObject;`在任何构造函数调用之前总是被调用,即使对于较旧的Delphi版本也是如此.你的评论是恕我直言,错误和混乱. (16认同)
  • 如果局部变量属于字符串,接口,动态数组或变体等托管类型,则初始化($ 0) (8认同)
  • 不要忘记,在一个返回字符串的函数中,'Result'没有像你期望的那样初始化为空字符串.这是因为'Result'不是本地var. (7认同)
  • 但是有一个例外!当你覆盖构造函数,并且不调用继承的构造函数时,某些字段有可能最终未初始化!(特别是使用较旧的Delphi版本.)由于TObject.Create负责归零所有数据,因此不会调用该数据导致可能的未知数据. (4认同)
  • 正如Giacomo在下面的评论中所指出的,这些都在ms-help://borland.bds4/bds4ref/html/Variables.htm中的Delphi帮助文件中进行了解释.在Delphi 2009中,我通过搜索"变量"的帮助找到了相同的信息(有趣的是,我尝试了很多搜索,但我没想过尝试那个). (2认同)
  • 如果这是"答案",我认为有人应该添加初始化的集合和枚举以保证完整性. (2认同)

Bar*_*lly 27

没有显式初始值设定项的全局变量在可执行文件的BSS部分中分配.它们实际上并没有占用EXE中的任何空间; BSS部分是OS分配并清除为零的特殊部分.在其他操作系统上,有类似的机制.

您可以依赖零初始化的全局变量.


Mar*_*sén 20

类字段默认为零.这是记录在案的,所以你可以依赖它.除非字符串或接口设置为零,否则本地堆栈可变量是未定义的.

  • 是的,正是如此.nil = 0(在汇编程序级别)和''= nil(Delphi约定). (4认同)
  • “除非字符串或接口”并不是对现实的完整描述。例如,动态数组也会被初始化。更一般地,规则是托管(引用计数)类型的变量被初始化,即使是本地变量。 (4认同)

Hei*_*cht 16

正如旁注(因为您是Delphi的新手):全局变量可以在声明它们时直接初始化:

var myGlobal:integer=99;
Run Code Online (Sandbox Code Playgroud)

  • 由于 10.3 同样适用于局部变量 (2认同)
  • 如果没有显式完成,它们将被初始化为 0、0.0、False、nil、[] 等。 (2认同)

Dre*_*son 8

以下是Ray Lischners Delphi在Nutshell 第2章中的引用

"当Delphi首次创建一个对象时,所有字段都开始为空,即指针初始化为nil,字符串和动态数组为空,数字值为零,布尔字段为False,Variants设置为Unassigned. (有关详细信息,请参阅第5章中的NewInstance和InitInstance.)"

确实需要初始化本地范围内的变量...我会将上面的注释"全局变量初始化"视为可疑,直到提供参考 - 我不相信.

编辑... Barry Kelly说你可以依赖它们进行零初始化,而且因为他在Delphi编译器团队中,我相信这就是:)感谢Barry.

  • 在delphi 2006帮助中你可以在这里找到它:ms-help://borland.bds4/bds4ref/html/Variables.htm“如果没有显式初始化全局变量,编译器将其初始化为0。对象实例数据(字段)也被初始化为 0。” (3认同)
  • 由于“我不相信”而被否决。这是编程,而不是宗教。贾科莫刚刚证明了事实。 (2认同)

Ond*_*lle 6

全局变量和对象实例数据(字段)始终初始化为零.程序和方法中的局部变量未在Win32 Delphi中初始化; 在代码中为它们分配值之前,它们的内容是未定义的.


Ond*_*lle 6

来自 Delphi 2007 帮助文件:

ms-help://borland.bds5/devcommon/variables_xml.html

“如果你没有显式初始化全局变量,编译器会将其初始化为 0。”


Lor*_*tel 6

我对给出的答案有一点抱怨。Delphi 将全局变量和新创建的对象的内存空间清零。虽然这通常意味着它们已初始化,但在一种情况下它们并未初始化:具有特定值的枚举类型。如果零不是合法值怎么办?

  • 如果您明确地将值分配给枚举,则零并不总是合法值。在这种情况下,它仍然被初始化为 0,并且您有一个非法值。但枚举只是在普通整数类型上绘制的语法糖,所以这并没有真正破坏任何东西。确保您的代码可以处理它。 (8认同)
  • @François:如果您像这样定义枚举,则不会:`TOOneTwoThree = (One=1, Two=2, Three=3);` (2认同)

Tho*_*ens 5

即使一种语言确实提供了默认初始化,我也不认为您应该依赖它们。对于可能不了解语言中默认初始化的其他开发人员来说,初始化为一个值可以更加清楚,并防止跨编译器出现问题。

  • 当然可以。你应该。在每个构造函数中将所有内容初始化为 0/''/false/nil 是不必要的。另一方面,初始化全局变量并不是那么愚蠢——我一次不记得它们是否被初始化(因为我没有经常使用它们)。 (4认同)
  • 如果 Delphi 允许您在声明变量的同一点初始化变量(例如 var fObject: TObject = nil),我倾向于同意初始化为一个值可能是一个好主意。但对我来说,在构造函数中为每个对象字段做这件事似乎有点多。 (2认同)