Да, на это можно положиться.
Все переменные с подсчетом ссылок:
- Струны;
- Динамические массивы;
- Варианты;
- Интерфейсы;
- Вложенные записи, содержащие такие переменные.
инициализируются на nil
при выделении record
, если вы используете New
или динамический массив - даже локально в стеке. Конечно, если вы используете простой GetMem
или работаете с указателями, вам придется инициализировать его самостоятельно (например, с помощью FillChar
).
Если вам интересно, есть скрытый вызов следующей процедуры System.pas:
procedure _InitializeRecord(p: Pointer; typeInfo: Pointer);
Это заполнит всю память переменных с подсчетом ссылок на 0, но не установит другие члены record
. Фактически, в экземпляре class
вся память поля инициализируется с 0, включая все элементы - для 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;