Sou novo no Delphi e tenho feito alguns testes para ver por quais variables de object e variables de pilha são inicializadas por padrão:
TInstanceVariables = class fBoolean: boolean; // always starts off as false fInteger: integer; // always starts off as zero fObject: TObject; // always starts off as nil end;
Este é o comportamento que eu estou acostumado em outros idiomas, mas eu estou querendo saber se é seguro confiar nele no Delphi? Por exemplo, eu estou querendo saber se pode depender de uma configuração de compilador, ou talvez trabalhar de forma diferente em máquinas diferentes. É normal confiar em valores inicializados padrão para objects ou você define explicitamente todas as variables de instância no construtor?
Quanto às variables de pilha (nível de procedimento), meus testes estão mostrando que booleanos unitializados são verdadeiros, inteiros unitializados são 2129993264 e objects não inicializados são apenas pointers inválidos (ou seja, não são nulos). Eu estou supondo que a norma é sempre definir variables de nível de procedimento antes de acessá-los?
Sim, este é o comportamento documentado:
Campos de object são sempre inicializados para 0, 0.0, ”, Falso, nulo ou o que for aplicável.
Variáveis globais são sempre inicializadas para 0 etc também;
Variáveis locais de referência * são sempre inicializadas como nulas ou ”;
As variables locais não contadas por referência * não são inicializadas, portanto você deve atribuir um valor antes de poder usá-las.
Eu lembro que Barry Kelly em algum lugar escreveu uma definição para “referência contada”, mas não pode mais encontrá-la, então isso deve acontecer enquanto isso:
contados por referência == que são contados por referência em si, ou direta ou indiretamente contêm campos (para registros) ou elementos (para matrizes) que são contados por referência como:
string, variant, interface
ou matriz dinâmica ou matriz estática contendo tais tipos.
Notas:
record
si não é suficiente para se tornar referência contada Variáveis globais que não possuem um inicializador explícito são alocadas na seção BSS no executável. Eles realmente não ocupam espaço no EXE; a seção BSS é uma seção especial que o SO aloca e limpa para zero. Em outros sistemas operacionais, existem mecanismos semelhantes.
Você pode depender de variables globais que são inicializadas com zero.
Campos de class são o padrão zero. Isso está documentado para que você possa confiar nele. Variáveis locais de pilha são indefinidas, a menos que seja uma string ou interface, elas são definidas como zero.
Apenas como uma nota lateral (como você é novo no Delphi): Variáveis globais podem ser inicializadas diretamente ao declará-las:
var myGlobal:integer=99;
Aqui está uma citação de Ray Lischners Delphi in a Nutshell Chapter 2
“Quando o Delphi primeiro cria um object, todos os campos começam vazios, isto é, os pointers são inicializados como inexistentes, os strings e arrays dynamics são vazios, os números têm o valor zero, os campos booleanos são False e Variantes são definidos como Não atribuídos. (Veja NewInstance e InitInstance no Capítulo 5 para detalhes.) ”
É verdade que as variables locais no escopo precisam ser inicializadas … Eu trataria o comentário acima que “Variáveis globais são inicializadas” como duvidosas até receberem uma referência – não acredito nisso.
editar … Barry Kelly diz que você pode depender deles serem inicializados com zero, e já que ele está na equipe de compiladores Delphi, eu acredito que isso acontece 🙂 Obrigado Barry.
Variáveis globais e dados de instância de object (campos) são sempre inicializados para zero. Variáveis locais em procedimentos e methods não são inicializadas no Win32 Delphi; seu conteúdo é indefinido até você atribuir um valor ao código.
A partir do arquivo de ajuda do Delphi 2007:
ms-help: //borland.bds5/devcommon/variables_xml.html
“Se você não inicializar explicitamente uma variável global, o compilador inicializa para 0.”
Eu tenho uma pequena reclamação com as respostas dadas. O Delphi zera o espaço de memory dos globals e dos objects recém-criados. Embora isso normalmente signifique que eles foram inicializados, há um caso em que eles não são: tipos enumerados com valores específicos. E se zero não é um valor legal?
Mesmo que uma linguagem ofereça inicializações padrão, não acredito que você deva confiar nelas. A boot para um valor torna muito mais claro para outros desenvolvedores que podem não saber sobre inicializações padrão no idioma e evita problemas em compiladores.