默认情况下,是否用值初始化了delphi变量?

时间:2020-03-06 14:42:56  来源:igfitidea点击:

我是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)。我猜测规范是总是在访问它们之前设置过程级变量?

解决方案

类字段默认为零。有文档记录,因此我们可以依靠它。
除非字符串或者接口将其设置为零,否则未定义本地堆栈变量。

是的,这是记录的行为:

  • 对象字段始终初始化为0、0.0,'',False,nil或者任何适用的字段。
  • 全局变量也总是初始化为0等。
  • 局部引用计数*变量始终初始化为nil或者'';
  • 本地非引用计数*变量未初始化,因此必须先分配一个值,然后才能使用它们。

我记得Barry Kelly在某个地方写了一个"引用计数"的定义,但是再也找不到了,因此在此期间应该这样做:

reference-counted == that are reference-counted themselves, or
  directly or indirectly contain fields (for records) or elements (for
  arrays) that are reference-counted like: string, variant, interface
  or dynamic array or static array containing such types.

笔记:

  • "记录"本身不足以成为引用计数
  • 我还没有尝试过使用泛型

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

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

这是Ray Lischners Delphi在《果壳》第2章中的引文

"When Delphi first creates an object, all of the fields start out empty, that is, pointers are initialized to nil, strings and dynamic arrays are empty, numbers have the value zero, Boolean fields are False, and Variants are set to Unassigned. (See NewInstance and InitInstance in Chapter 5 for details.)"

的确,需要初始化局部作用域变量...我将上面的评论"全局变量已初始化"视为可疑,直到提供了我不相信的参考。

编辑...
Barry Kelly说,我们可以依靠将它们初始化为零,并且由于他在Delphi编译器团队中,所以我相信这是正确的:)感谢Barry。

从Delphi 2007帮助文件中:

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

"If you don't explicitly initialize a global variable, the compiler initializes it to 0."

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

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

我们可以依赖全局变量被零初始化。

就像一个旁注(因为我们是Delphi的新手):在声明全局变量时可以直接对其进行初始化:

var myGlobal:integer=99;