我是否需要在初始化时将setLength设置为动态数组?

pop*_*p32 3 delphi delphi-xe

type Tmyclass = class(TObject)
  somearray: array of TSometype
  FBool: Boolean;
  Fint: Integer;
  Fstr: string;
  constructor Create;
  destructor Destroy; override;
end;

implementation

constructor Tmyclass.Create;
begin
  inherited;
  SetLength(somearray,0); //is this needed?
end;

destructor TmyClass.Destroy;
begin
  SetLength(somearray,0); //this IS needed!
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

还有什么类型在创建时初始化?例如我在课堂上宣布的内容.FBool被保证是假的吗?是FInt保证是0吗?是Fstr保证是''?

当地情况怎么样?只有字符串?

我使用Delphi XE.

jac*_*ate 13

属于对象的所有内存在对象构造(堆分配)时初始化为0,因此通常不需要初始化属于类的任何内容,默认值(零内存)是:

  • 字符串将是''
  • 整数将为0
  • 浮点变量将为0
  • 布尔值为false
  • 指针和对象引用将为零
  • 动态数组将包含零元素.

等等.

对于局部变量和与堆栈相关的任何东西,它将包含垃圾,因此您需要在使用变量之前提供有意义的值.

就像是:

procedure Something;
var
  x: Integer;
begin
  ShowMessage(IntToStr(X));
end;
Run Code Online (Sandbox Code Playgroud)

将显示随机值.

  • @ pop32 SetLength为0不是必需的,动态数组将包含0个元素. (3认同)
  • 那么构造函数中的SetLength呢? (2认同)

Dav*_*nan 13

动态数组是托管类型,因此始终初始化为nil,等效于SetLength(..., 0).你永远不需要这样做.

唯一可以捕获的是当您从过程返回动态数组作为函数返回值时.事实上,函数返回值实际上只是一个隐式的var参数.

请考虑以下代码:

function Foo: string;
begin
  Result := Result + 'X';
end;

var
  i: Integer;

begin
  for i := 1 to 5 do
    Writeln(Foo);
  Writeln(Foo);
  Writeln(Foo);
end;
Run Code Online (Sandbox Code Playgroud)

产量

X
XX
XXX
XXXX
XXXXX
X
X
Run Code Online (Sandbox Code Playgroud)

这里发生的是编译器作为优化选择不重新初始化循环内的隐式局部变量.

这可能会不时地让你失意,所以我建议设置为nil返回值,这些值是动态数组,字符串,接口等.对于类成员你不需要这样做,并且让构造函数对它们进行零初始化是更惯用的自动.


Uli*_*rdt 7

由于动态数组已初始化并最终确定,因此两个 SetLength调用都是多余的.

类实例中的所有字段都初始化为它们各自的零值,即0,nil,False,''等.

只有当局部变量属于生命周期管理类型(如字符串,动态数组或接口)时,才会初始化(并最终确定)局部变量.


Mar*_*ema 5

正如其他回答者所说,您不需要初始化类成员字段。

您还询问了局部变量。是的,您确实需要初始化它们。所有这些,除了托管类型之一的变量:

  • Ansi字符串
  • Unicode字符串
  • 宽弦
  • 接口类型
  • 动态数组类型
  • 变体

列表取自 Barry Kelly 的回答,Sertac 在评论中指出:Which Variables are initialized while in Delphi?