107

我是 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;

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

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

4

10 回答 10

109

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

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

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

  • 局部引用计数* 变量总是初始化为 nil 或 '';

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

我记得Barry Kelly在某处为“引用计数”写了一个定义,但再也找不到它了,所以同时应该这样做:

引用计数 == 本身是引用计数的,或者直接或间接包含引用计数的字段(用于记录)或元素(用于数组),例如:string, variant, interface 或包含此类类型的动态数组静态数组。

笔记:

  • record本身不足以成为引用计数
  • 我还没有用泛型试过这个
于 2008-09-25T11:41:38.347 回答
27

没有显式初始化程序的全局变量在可执行文件的 BSS 部分中分配。它们实际上并不占用 EXE 中的任何空间;BSS 部分是操作系统分配并清零的特殊部分。在其他操作系统上,也有类似的机制。

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

于 2008-09-25T15:58:33.033 回答
21

类字段默认为零。这已记录在案,因此您可以依赖它。本地堆栈变量是未定义的,除非字符串或接口,这些设置为零。

于 2008-09-25T11:33:12.017 回答
18

顺便说一句(因为您是 Delphi 新手):全局变量可以在声明它们时直接初始化:

var myGlobal:integer=99;
于 2009-01-30T13:30:56.060 回答
7

这是 Ray Lischners Delphi in a Nutshell Chapter 2的一句话

“当Delphi第一次创建一个对象时,所有的字段一开始都是空的,也就是说,指针被初始化为nil,字符串和动态数组都是空的,数字的值为零,布尔字段为False,Variants被设置为Unassigned。 (详见第 5 章的 NewInstance 和 InitInstance。)"

确实需要初始化范围内的局部变量......我认为上面的评论“全局变量已初始化”是可疑的,直到提供参考 - 我不相信。

编辑... Barry Kelly 说您可以依赖它们进行零初始化,并且由于他在 Delphi 编译器团队中,我相信这是 :) 谢谢 Barry。

于 2008-09-25T12:03:05.690 回答
6

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

于 2008-09-25T11:42:22.900 回答
5

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

于 2008-09-25T11:57:51.303 回答
4

来自 Delphi 2007 帮助文件:

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

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

于 2008-09-25T14:27:33.347 回答
3

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

于 2008-09-25T14:46:04.767 回答
0

新引入的(自 Delphi 10.3 起)内联变量使初始值的控制更加容易。

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
于 2020-08-05T13:56:03.483 回答