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

时间:2011-03-15 16:38:49

标签: 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;

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

当地人怎么样?只有字符串?

我使用的是Delphi XE。

5 个答案:

答案 0 :(得分:13)

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

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

等等。

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

类似的东西:

procedure Something;
var
  x: Integer;
begin
  ShowMessage(IntToStr(X));
end;

将显示随机值。

答案 1 :(得分: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;

<强>输出

X
XX
XXX
XXXX
XXXXX
X
X

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

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

答案 2 :(得分:7)

两个 SetLength调用都是多余的,因为动态数组已初始化并完成。

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

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

答案 3 :(得分:4)

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

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

  • AnsiString类型
  • 的UnicodeString
  • WideString的
  • 接口类型
  • 动态数组类型
  • 变体

来自Barry Kelly在Sertac在评论中指出的答案的清单:Which variables are initialized when in Delphi?

答案 4 :(得分:0)

如果您事先知道阵列的大小,将它作为一个整体进行分配可能是一个好习惯,它将在以后避免过多的重新分配,更好地使用内存。当你不再使用它时清除数组会释放它的内存(但Delphi知道如何在它们超出范围时清除它们)。