我可以依赖这样一个事实,即记录中的接口字段是否始终初始化为nil?
TMyRec = record
FGuard : IInterface;
FObject : TObject;
procedure CheckCreated;
end;
Run Code Online (Sandbox Code Playgroud)
这将允许我写:
procedure TMyCheck.CheckCreated;
begin
if (FGuard = nil) then
begin
FObject := TObject.Create;
FGuard := TGuard.Create (FObject);
end;
end;
Run Code Online (Sandbox Code Playgroud)
(用于自动终身管理)
我知道接口字段已初始化为,nil但是当包含在记录中时也是如此?
是的,你可以依靠它.
所有参考计数变量:
如果你使用或动态数组 - 甚至在堆栈本地,则初始化为nila .当然,如果你使用普通或使用指针,你必须自己初始化它(例如使用a ).recordNewGetMemFillChar
如果您很好奇,则会对System.pas的以下过程进行隐藏调用:
procedure _InitializeRecord(p: Pointer; typeInfo: Pointer);
Run Code Online (Sandbox Code Playgroud)
这会将所有引用计数变量内存填充为0,但不会设置其他成员record.实际上,在一个class实例中,整个字段内存初始化为0,包括所有成员 - 对于a record,初始化仅用于引用计数类型.
请注意,在某些情况下,我发现如果您使用object类型而不是record- 至少在Delphi 2009-2010下,这种初始化没有正确生成.因此,如果您的代码有一些object类型声明,您可以更好地切换到record(和松散的继承),或显式调用FillChar.
如果您很好奇,这是我在asm中编写的优化版本 - 可在我们的增强型RTL中找到.
procedure _InitializeRecord(p: Pointer; typeInfo: Pointer);
// this procedure is called at most object creation -> optimization rocks here!
asm
{ -> EAX pointer to record to be initialized }
{ EDX pointer to type info }
MOVZX ECX,[EDX+1] { type name length }
PUSH EBX
PUSH ESI
PUSH EDI
MOV EBX,EAX // PIC safe. See comment above
LEA ESI,[EDX+ECX+2+8] { address of destructable fields }
MOV EDI,[EDX+ECX+2+4] { number of destructable fields }
@@loop:
mov edx,[esi] // type info
mov eax,[esi+4]
mov edx,[edx]
add esi,8
add eax,ebx // data to be initialized
movzx ecx,[edx] // data type
cmp ecx,tkLString
je @@LString
jb @@err
cmp ecx,tkDynArray
je @@DynArray
ja @@err
jmp dword ptr [ecx*4+@@Tab-tkWString*4]
nop; nop; nop // align @@Tab
@@Tab: dd @@WString,@@Variant,@@Array,@@Record
dd @@Interface,@@err
@@LString:
@@WString:
@@Interface:
@@DynArray: // zero 4 bytes in EAX
dec edi
mov dword ptr [eax],0
jg @@loop
POP EDI
POP ESI
POP EBX
RET
@@Variant: // zero 16 bytes in EAX
xor ecx,ecx
dec edi
mov [eax],ecx
mov [eax+4],ecx
mov [eax+8],ecx
mov [eax+12],ecx
jg @@loop
jmp @@exit
@@err:
MOV AL,reInvalidPtr
POP EDI
POP ESI
POP EBX
JMP Error
@@Array:
@@Record: // rarely called in practice
mov ecx,1
call _InitializeArray
dec edi
jg @@loop
@@exit:
POP EDI
POP ESI
POP EBX
end;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
688 次 |
| 最近记录: |