当前位置:  开发笔记 > 编程语言 > 正文

如何初始化var Record参数

如何解决《如何初始化varRecord参数》经验,为你挑选了1个好方法。

我有记录类型:

type
  TIPInfo = record
    IP,
    HostName,
    City,
    Region,
    Country,
    Loc,
    Org: WideString
  end;

函数返回记录数据:

function GetPublicIPInfo(var IPInfo: TIPInfo): Boolean;
begin
  // initialize
  FillChar(IPInfo, SizeOf(TIPInfo), 0);

  // populate data
  IPInfo.IP := GetVallue('ip');
  IPInfo.HostName := GetVallue('hostname');
  IPInfo.City := GetVallue('city');
  // etc...

  Result := IsOk;   
end;

呼叫者,召集者:

var
  IPInfo: TIPInfo;

if GetPublicIPInfo(IPInfo) then... // use data

它是var TIPInfo通过调用初始化的正确方法FillChar还是应该将每个字段设置为空字符串?来电者应该这样做吗?

此外,out在案例中使用参数会更好吗(因为函数不读取数据)?



1> David Heffer..:

FillChar在这里使用just 是错误的.如果任何WideString成员不是空的,那么你会以这种方式泄漏它们.相反,我建议如下:

Finalize(IPInfo);
FillChar(IPInfo, SizeOf(TIPInfo), 0);

或者另一种方法是将默认记录定义为类型化常量:

const
  DefaultIPInfo: TIPInfo = ();

然后你可以使用简单的赋值:

IPInfo := DefaultIPInfo;

在现代版本的Delphi中,您可以使用这个更易读的代码:

IPInfo := Default(TIPInfo);

有关此特定主题的更多信息,请参阅以下主题:

Delphi"default"关键字,旧版Delphi版本中包含Record类型.

如何在Delphi中正确释放包含各种类型的记录?

请注意,代码中的泄漏很难找到,因为WideString变量是作为COM BSTR对象实现的,并在COM堆上分配.因此,如果对Delphi内存管理器使用内存泄漏检测,则不会检测到泄漏,因为它是从不同的堆泄漏的.

在您的情况下,因为您的记录是托管类型,并且只包含托管类型,所以您可以使用out参数以获得良好的效果.对于托管类型,out参数意味着编译器将在调用站点生成代码,以在传递记录之前默认初始化记录.

考虑以下程序:

{$APPTYPE CONSOLE}

type
  TRec = record
    Value: WideString;
  end;

procedure Foo1(var rec: TRec);
begin
end;

procedure Foo2(out rec: TRec);
begin
end;

procedure Main;
var
  rec: TRec;
begin
  rec.Value := 'Foo';
  Foo1(rec);
  Writeln(rec.Value);
  Foo2(rec);
  Writeln(rec.Value);
end;

begin
  Main;
end.

输出是:

Foo

如果您的记录包含托管和非托管类型的混合,那么情况就不那么好了.

{$APPTYPE CONSOLE}

type
  TRec = record
    Value1: WideString;
    Value2: Integer;
  end;

procedure Foo1(var rec: TRec);
begin
end;

procedure Foo2(out rec: TRec);
begin
end;

procedure Main;
var
  rec: TRec;
begin
  rec.Value1 := 'Foo';
  rec.Value2 := 42;
  Foo1(rec);
  Writeln(rec.Value1);
  Writeln(rec.Value2);
  Foo2(rec);
  Writeln(rec.Value1);
  Writeln(rec.Value2);
end;

begin
  Main;
end.

输出是:

Foo
42

42

仅默认为out参数初始化托管成员.因此,最好的办法是默认自己初始化变量,即使它是作为out参数传递的.

有关out参数的更多信息,请参见:"var"和"out"参数之间的区别是什么?

推荐阅读
mobiledu2402851377
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有