我只是想知道为什么大多数Delphi示例使用FillChar()来初始化记录.
type
TFoo = record
i: Integer;
s: string; // not safe in record, better use PChar instead
end;
const
EmptyFoo: TFoo = (i: 0; s: '');
procedure Test;
var
Foo: TFoo;
s2: string;
begin
Foo := EmptyFoo; // initialize a record
// Danger code starts
FillChar(Foo, SizeOf(Foo), #0);
s2 := Copy("Leak Test", 1, MaxInt); // The refcount of the string buffer = 1
Foo.s = s2; // The refcount of s2 = 2
FillChar(Foo, SizeOf(Foo), #0); // The refcount …Run Code Online (Sandbox Code Playgroud) 我有一个像这样定义的结构:
const
MaxSignalRecords=255;
type
TSignalRecord=record
signal1 : integer;
signal2 : integer;
signal3 : integer;
signal4 : integer;
signal5 : integer;
signal6 : integer;
bsignal1 : Boolean;
bsignal2 : Boolean;
bsignal3 : Boolean;
bsignal4 : Boolean;
bsignal5 : Boolean;
bsignal6 : Boolean;
end;
TListSignals = Array[0..MaxSignalRecords-1] of TSignalRecord;
Run Code Online (Sandbox Code Playgroud)
此结构用于在如下算法中进行数千次计算:
for i:=1 to 900000 do
begin
CleartheList(MyList);
DotheMath(MyList);
DotheChart(MyList);
end;
Run Code Online (Sandbox Code Playgroud)
我正在寻找一种快速的方法来将我的值初始化TListSignals为0和false.
现在我用这个:
procedure ClearListSignals(var ListSignals:TListSignals);
var
i :Integer;
begin
for i := 0 to MaxSignalRecords - 1 do …Run Code Online (Sandbox Code Playgroud) 在我的申请中,我有以下记录:
TTransaction = record
Alias: string
Description: string
Creation: TDateTime
Count: Integer
end;
Run Code Online (Sandbox Code Playgroud)
我在这个数组中使用此记录:
Transactions = array of TTransaction;
Run Code Online (Sandbox Code Playgroud)
我在运行时保持数组加载,但在给定时间我需要清除所有数据并添加一些新数据.
仅仅使用它就足够了:
SetLength(Transactions, 0); ?
Run Code Online (Sandbox Code Playgroud)
或者我需要完成一些事情吗?
我在类的方法中使用由字符串,布尔值,整数,货币和其他记录数组组成的记录.我想以递归方式初始化基本类型的所有字段为空/假/零.默认情况下,Delphi似乎不这样做.是否有一种直接的方法来实现这一点,不涉及通过名称访问每个字段并手动设置它?
假设您有一个您想要初始化的本地记录:
type
TMyRec=record
Val1, Val2:Integer;
end;
procedure MyProc;
var
MyVar:TMyRec;
begin
// ... ?
WriteLn(Val1,Val2);
end;
Run Code Online (Sandbox Code Playgroud)
除了"手动"设置每个字段外,还有几种方法可以实现.
使用Initialize():
Initialize(MyVar);
Run Code Online (Sandbox Code Playgroud)使用默认值():
MyVar := Default(TMyVar);
Run Code Online (Sandbox Code Playgroud)使用FillChar:
FillChar(MyVar,SizeOf(MyVar),0);
Run Code Online (Sandbox Code Playgroud)定义一个空常量,并将其赋值给var
const cMyVar:TMyVar=();
...
MyVar := cMyVar;
Run Code Online (Sandbox Code Playgroud)以上所有似乎都适用于这个例子.我想你甚至可以定义一个全局变量来初始化它.
但是有一种首选方法吗?或者在某些情况下,不建议使用上述任何一种情况,或者它根本不起作用?
把它短,有什么明确的正确方法TM初始化一个局部堆栈变量?:-)
我有2条记录,如下所示:
TYPE
TRecord2= packed record
i2: Integer;
end;
TRecord1= packed record
i1: Integer;
R2: TRecord2;
end;
Run Code Online (Sandbox Code Playgroud)
.
我想将记录字段初始化为零,但我不想使用FillMemory,因此我声明了2个常量记录,我在其中初始化字段.
CONST
Record2c: TRecord2=
(
i2: 0;
);
Record1c: TRecord1=
(
i1: 0;
R2: Record2c; <------- error line
);
Run Code Online (Sandbox Code Playgroud)
但是,我无法将Record2c分配给R2字段.编译器说:E2029'('期望但标识符'Record2c'找到.
但这有效(如果我评论我有错误的行):
procedure test;
var Record1: TRecord1;
begin
Record1:= Record1c; // initialize variable by associating the constant to it
end
Run Code Online (Sandbox Code Playgroud)
那么,我如何初始化R2字段?
我可以将"任何"记录类型传递给我的程序吗?
我多次使用带有字符串的"记录".
type
TR = record
a: string;
b: string;
end;
Run Code Online (Sandbox Code Playgroud)
要清除它们,我需要写:
Finalize(R);
FillChar(R, SizeOf(R), #0);
Run Code Online (Sandbox Code Playgroud)
问题是如何通过任何类型的记录来清除它?
为此我得到了这个提示:"表达式不需要初始化/完成".
procedure ClearRecord(var R);
begin
Finalize(R);
FillChar(R, SizeOf(R), #0);
end;
Run Code Online (Sandbox Code Playgroud)
感谢您的每一个信息!
我有记录类型:
type
TIPInfo = record
IP,
HostName,
City,
Region,
Country,
Loc,
Org: WideString
end;
Run Code Online (Sandbox Code Playgroud)
函数返回记录数据:
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;
Run Code Online (Sandbox Code Playgroud)
呼叫者,召集者:
var
IPInfo: TIPInfo;
if GetPublicIPInfo(IPInfo) then... // use data
Run Code Online (Sandbox Code Playgroud)
它是var TIPInfo通过调用初始化的正确方法FillChar还是应该将每个字段设置为空字符串?来电者应该这样做吗?
此外,out在案例中使用参数会更好吗(因为函数不读取数据)?
我正在使用RAD XE7.在我的Delphi应用程序中,我想为Records字段设置默认值.
我尝试了下面的代码,但它没有编译,我知道这是错误的.我还有别的办法吗?
TDtcData = record
TableFormat : TExtTableFormat = fmNoExtendedData;
DTC : integer = 0;
Description : string = 'Dummy';
Status : TDtcStatus;
OccurenceCnt : integer =20;
FirstDTCSnapShot: integer;
LastDTCSnapShot: integer;
end;
Run Code Online (Sandbox Code Playgroud) 将默认值(TMyRecord)分配给TMyRecord的变量称为内部调用Finalize,然后将内存清零,就像FillChar那样.例如,在以下问题的答案中已经说过,我确实测试过分配Default()确实会导致调用例如System._FinalizeRecord
Initialize(),Default()和FillChar()之间的区别
我的问题是,即使在Delphi没有自动调用Initialize的情况下,初始化这样的记录是否总是安全的?对我来说,在未初始化的记录变量上调用Finalize似乎没有意义.在初始化之前,必须假定内存包含随机垃圾.在这种情况下,我对托管类型特别感兴趣,这些托管类型是动态分配内存的指针,Finalize例程应该通过减少它们的引用计数来完成,等等.在许多情况下,Delphi会自动生成对Initialize的调用,以确保其托管类型保持可管理状态.但不总是.
这是一个示例,说明了一个有问题的案例.正如下面的答案所述,你不应该使用GetMem来分配包含这样的托管类型的记录,但是让我们假设某人做了,然后尝试使用Default()赋值作为初始化
type
TMyRecord = record
s1, s2, s3 : String;
end;
PMyRecord = ^TMyRecord;
var
pr : PMyRecord;
begin
GetMem(pr, SizeOf(TMyRecord));
pr^ := Default(TMyRecord);
...
Run Code Online (Sandbox Code Playgroud)
我故意使用GetMem()而不是New(),因为据我所知,GetMem()返回的内存不应该自动归零,并且编译器不应该自动调用Initialize.那么在这种情况下,使用默认分配初始化记录不是不安全吗?
在大卫接受的答案中,他正在使用一种漂亮的Clear方法记录类型 如何在Delphi中正确释放包含各种类型的记录? 让我们添加一个
TMyRecord = record
s1, s2, s3 : String;
procedure Clear;
end;
...
procedure TMyRecord.Clear;
begin
Self := Default(TMyRecord);
end;
Run Code Online (Sandbox Code Playgroud)
现在,Clear例程应该完全无法知道记录是否位于堆栈或堆上,并且是否已在其上调用Initialize.
delphi ×10
record ×4
delphi-6 ×2
clear ×1
default ×1
delphi-7 ×1
delphi-xe7 ×1
finalization ×1
finalize ×1