type
TSomeRecord = Record
field1: integer;
field2: string;
field3: boolean;
End;
var
SomeRecord: TSomeRecord;
SomeRecAr: array of TSomeRecord;
Run Code Online (Sandbox Code Playgroud)
这是我所拥有的最基本的例子,因为我想重复使用SomeRecord
(某些字段保持为空,没有释放所有字段将在重复使用时被转移SomeRecord
,这显然是不受欢迎的)我正在寻找一种方法一次释放所有字段.我已经开始string[255]
使用ZeroMemory()
,这很好,直到它开始泄漏内存,这是因为我切换到string
.我仍然缺乏了解原因的知识,但似乎与动态有关.我也在使用动态数组,因此我认为尝试ZeroMemory()
任何动态都会导致泄漏.有一天浪费了这一点.我想,我通过使用解决了这个Finalize()
上SomeRecord
或SomeRecAr
之前ZeroMemory()
,但我不知道这是正确的做法,或只是我太傻了.
所以问题是:如何一次性解放所有东西?是否存在一些我不知道的单一程序?
换句话说,或者我会建议如何以不同的方式实现这些记录,所以我不需要做出复杂的尝试来释放东西.我已经研究过创建记录New()
然后去掉它Dispose()
,但我不知道当调用之后的变量Dispose()
是未定义的而不是nil 时它意味着什么.另外,我不知道某个type(SomeRecord: TSomeRecord
)的变量与指向type()的变量之间的区别是什么SomeRecord: ^TSomeRecord
.我现在正在调查上述问题,除非有人能够快速解释,否则可能需要一些时间.
Dav*_*nan 27
假设您有一个支持在记录上实现方法的Delphi版本,您可以清除这样的记录:
type
TSomeRecord = record
field1: integer;
field2: string;
field3: boolean;
procedure Clear;
end;
procedure TSomeRecord.Clear;
begin
Self := Default(TSomeRecord);
end;
Run Code Online (Sandbox Code Playgroud)
如果您的编译器不支持,Default
那么您可以像这样完全相同:
procedure TSomeRecord.Clear;
const
Default: TSomeRecord=();
begin
Self := Default;
end;
Run Code Online (Sandbox Code Playgroud)
您可能更愿意避免在方法中改变值类型.在这种情况下,创建一个返回空记录值的函数,并将其与赋值运算符一起使用:
type
TSomeRecord = record
// fields go here
class function Empty: TSomeRecord; static;
end;
class function TSomeRecord.Empty: TSomeRecord;
begin
Result := Default(TSomeRecord);
end;
....
Value := TSomeRecord.Empty;
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我找不到任何文档参考Default(TypeIdentifier)
.有谁知道它在哪里可以找到?
至于问题的第二部分,我认为没有理由不继续使用记录,并使用动态数组分配它们.试图自己管理生命周期更容易出错.
不要让思想过于复杂!
分配"默认" record
只是CPU功耗和内存的损失.
当a在a record
中声明时TClass
,它被填充为零,因此被初始化.当它在堆栈上分配时,只初始化引用计数变量:其他类型的变量(如整数或双精度或布尔值或枚举)处于随机状态(可能非零).当它将在堆上分配时,getmem
将不会初始化任何内容,allocmem
将所有内容填充为零,并将new
仅初始化引用计数的成员(如在堆栈初始化时):在所有情况下,您应该使用其中任何一个dispose
,要么finalize+freemem
释放一个堆分配record
.
所以关于你的确切问题,你自己的假设是正确的:在使用后重置记录内容,永远不要使用" fillchar
"(或" zeromemory
")而不使用前一个" finalize
".这是正确和最快的方式:
Finalize(aRecord);
FillChar(aRecord,sizeof(aRecord),0);
Run Code Online (Sandbox Code Playgroud)
再次,它将比分配默认记录更快.并且在所有情况下,如果您使用Finalize
,甚至多次,它将不会泄漏任何内存 - 100%退款保修!
编辑:在查看生成的代码之后aRecord := default(TRecordType)
,代码得到了很好的优化:它实际上是Finalize
一堆stosd
模拟的代码FillChar
.因此,即使语法是copy/assignement(:=
),它也不会实现为复制/赋值.我的错误在这里.
但我仍然不喜欢:=
必须使用的事实,Embarcadero应该更好地使用record
像aRecord.Clear
语法一样的方法,就像DelphiWebScript的动态数组一样.实际上,这种:=
语法与C#使用的语法完全相同.听起来如果Embacardero在任何地方都模仿C#语法,却没有发现这很奇怪.如果德尔福只是一个追随者,而不是实施者认为"它的方式"是什么意思呢?人们总是更喜欢原始的C#到它的祖先(Delphi有同样的父亲).
我想到的最简单的解决方案是:
const
EmptySomeRecord: TSomeRecord = ();
begin
SomeRecord := EmptySomeRecord;
Run Code Online (Sandbox Code Playgroud)
但要解决问题的所有其余部分,请采用以下定义:
type
PSomeRecord = ^TSomeRecord;
TSomeRecord = record
Field1: Integer;
Field2: String;
Field3: Boolean;
end;
TSomeRecords = array of TSomeRecord;
PSomeRecordList = ^TSomeRecordList;
TSomeRecordList = array[0..MaxListSize] of TSomeRecord;
const
EmptySomeRecord: TSomeRecord = ();
Count = 10;
var
SomeRecord: TSomeRecord;
SomeRecords: TSomeRecords;
I: Integer;
P: PSomeRecord;
List: PSomeRecordList;
procedure ClearSomeRecord(var ASomeRecord: TSomeRecord);
begin
ASomeRecord.Field1 := 0;
ASomeRecord.Field2 := '';
ASomeRecord.Field3 := False;
end;
function NewSomeRecord: PSomeRecord;
begin
New(Result);
Result^.Field1 := 0;
Result^.Field2 := '';
Result^.Field3 := False;
end;
Run Code Online (Sandbox Code Playgroud)
然后是一些关于如何操作它们的例子:
begin
// Clearing a typed variable (1):
SomeRecord := EmptySomeRecord;
// Clearing a typed variable (2):
ClearSomeRecord(SomeRecord);
// Initializing and clearing a typed array variabele:
SetLength(SomeRecords, Count);
// Creating a pointer variable:
New(P);
// Clearing a pointer variable:
P^.Field1 := 0;
P^.Field2 := '';
P^.Field3 := False;
// Creating and clearing a pointer variable:
P := NewSomeRecord;
// Releasing a pointer variable:
Dispose(P);
// Creating a pointer array variable:
ReallocMem(List, Count * SizeOf(TSomeRecord));
// Clearing a pointer array variable:
for I := 0 to Count - 1 do
begin
Pointer(List^[I].Field2) := nil;
List^[I].Field1 := 0;
List^[I].Field2 := '';
List^[I].Field3 := False;
end;
// Releasing a pointer array variable:
Finalize(List^[0], Count);
Run Code Online (Sandbox Code Playgroud)
根据需要选择和/或组合.
归档时间: |
|
查看次数: |
13039 次 |
最近记录: |