Delphi değişkenleri varsayılan olarak bir değerle mi başlatılır?


103

Delphi'de yeniyim ve varsayılan olarak hangi nesne değişkenlerinin ve yığın değişkenlerinin başlatıldığını görmek için bazı testler çalıştırıyorum:

TInstanceVariables = class
  fBoolean: boolean; // always starts off as false
  fInteger: integer; // always starts off as zero
  fObject: TObject; // always starts off as nil
end;

Bu, diğer dillerde alıştığım davranış, ama Delphi'de buna güvenmenin güvenli olup olmadığını merak ediyorum. Örneğin, bir derleyici ayarına bağlı olup olmadığını veya belki farklı makinelerde farklı çalışıp çalışmayacağını merak ediyorum. Nesneler için varsayılan olarak başlatılmış değerlere güvenmek normal mi, yoksa yapıcıdaki tüm örnek değişkenlerini açık bir şekilde mi ayarlıyorsunuz?

Yığın (yordam düzeyi) değişkenlere gelince, testlerim birimleştirilmiş boolelerin doğru olduğunu, birimleştirilmiş tam sayıların 2129993264 olduğunu ve gerçekleştirilmemiş nesnelerin geçersiz işaretçiler olduğunu (yani sıfır olmadığını) gösteriyor. Sanırım norm, onlara erişmeden önce her zaman prosedür düzeyinde değişkenleri ayarlamak mı?


3
İki not: 1. Kayıtlar başlatılmaz. 2. Referans sayılan değişkenler her zaman başlatılır. !FAKAT! Bir dizge döndüren bir işlevde, beklediğiniz gibi 'Sonuç' boş dizge olarak başlatılmaz. Bunun nedeni, 'Sonuç'un yerel bir değişken olmamasıdır. Yani, her zaman şunu yapın: Sonuç: = '';
InTheNameOfScience


Yanıtlar:


105

Evet, belgelenen davranış budur:

  • Nesne alanları her zaman 0, 0.0, '', False, nil veya hangisi uygunsa o şekilde başlatılır.

  • Global değişkenler her zaman 0 vb. İle başlatılır;

  • Yerel referans sayılan * değişkenler her zaman sıfır veya '' olarak başlatılır;

  • Referans sayılmayan yerel * değişkenler başlatılmamış olduğundan, bunları kullanmadan önce bir değer atamanız gerekir.

Barry Kelly'nin bir yerlerde "referans sayılan" için bir tanım yazdığını, ancak artık bulamadığını hatırlıyorum , bu yüzden bu arada şunu yapmalı:

Kendileri başvuru sayılan başvuru sayılan == veya doğrudan veya dolaylı olarak alanlar (kayıtlar için) veya referans sayılan öğeler (diziler için): string, variant, interface veya dinamik dizi veya bu tür türleri içeren statik dizi içerir.

Notlar:

  • record kendisi referans olarak sayılmak için yeterli değildir
  • Bunu henüz jeneriklerle denemedim

2
Giacomo'nun aşağıdaki yorumlarda işaret ettiği gibi, bunların tümü, ms-help: //borland.bds4/bds4ref/html/Variables.htm adresindeki Delphi yardım dosyalarında açıklanmıştır. Delphi 2009'da "değişkenler" için yardımda arama yaparak aynı bilgiyi buldum (yeterince komik bir şekilde birçok arama denedim ama bunu denemeyi düşünmedim).
MB.

8
Dizeler, arayüzler, dinamik diziler veya varyantlar gibi yönetilen bir türden iseler yerel değişkenler başlatılır (0 $)
Francesca

5
Yine de bir istisna var! Yapıcıyı geçersiz kıldığınızda ve devralınan kurucuyu çağırmadığınızda, bazı alanların başlatılmamış olma ihtimali vardır! (Özellikle eski Delphi sürümlerinde.) TObject.Create tüm verileri sıfırlamaktan sorumlu olduğundan, onu çağırmamak olası bilinmeyen verilerle sonuçlanır.
Wim ten Brink

18
@WimtenBrink Bence yanılıyorsun. Başlatma, TObject.Createbir void yöntemi olan, ancak class function TObject.InitInstance(Instance: Pointer): TObject;daha eski Delphi sürümleri için bile herhangi bir yapıcı çağrısından önce HER ZAMAN çağrılan içinde yapılmaz . Yorumunuz IMHO yanlış ve kafa karıştırıcı.
Arnaud Bouchez

7
Bir dizge döndüren bir işlevde, 'Sonuç'un beklediğiniz gibi boş dizge olarak başlatılmadığını unutmayın. Bunun nedeni, 'Sonuç'un yerel bir değişken olmamasıdır.
InTheNameOfScience

27

Açık bir başlatıcıya sahip olmayan global değişkenler, yürütülebilir dosyanın BSS bölümünde ayrılır. EXE'de yer kaplamazlar; BSS bölümü, işletim sisteminin tahsis ettiği ve sıfıra temizlediği özel bir bölümdür. Diğer işletim sistemlerinde benzer mekanizmalar vardır.

Sıfır olarak başlatılan global değişkenlere güvenebilirsiniz.


21

Sınıf alanları varsayılan sıfırdır. Bu belgelenmiştir, böylece ona güvenebilirsiniz. Yerel yığın değişkenleri, dize veya arayüz olmadıkça tanımsızdır, bunlar sıfıra ayarlanır.


Teşekkürler. "Sıfır" beni biraz karıştırıyor - bu dizelerin '' olduğu ve arayüzlerin sıfır olduğu anlamına mı geliyor?
MB.

4
Evet, aynen öyle. nil = 0 (derleyici düzeyinde) ve '' = nil (Delphi kuralı).
gabr

1
"dizi veya arayüz olmadığı sürece" gerçekliğin tam bir açıklaması değildir. Örneğin dinamik diziler de başlatılır. Daha genel olarak kural, yönetilen (referans sayılan) türlerin değişkenlerinin yerel olsa bile başlatılmasıdır.
Andreas Rejbrand

16

Bir yan not olarak (Delphi'de yeni olduğunuz gibi): Global değişkenler, onları bildirirken doğrudan başlatılabilir:

var myGlobal:integer=99;

2
10.3 aynı yerel değişkenler için de geçerli olduğundan
Edijs Kolesnikovičs

1
Ve açıkça yapılmadıysa, 0, 0.0, False, nil, [], vb.
İle

7

İşte Ray Lischners Delphi'den Özetle Bölüm 2'den bir alıntı

"Delphi ilk kez bir nesne oluşturduğunda, tüm alanlar boş olarak başlar, yani işaretçiler sıfır olarak başlatılır, dizeler ve dinamik diziler boştur, sayılar sıfır değerine sahiptir, Boolean alanları False ve Varyantlar Atanmamış olarak ayarlanır. (Ayrıntılar için 5. Bölümdeki NewInstance ve InitInstance konusuna bakın.) "

Yerel kapsam içi değişkenlerin başlatılması gerektiği doğrudur ... Yukarıdaki "Global değişkenler başlatılır" yorumunu bir referans sağlanana kadar şüpheli olarak ele alacağım - buna inanmıyorum.

edit ... Barry Kelly onların sıfır sıfırlanmasına güvenebileceğinizi söylüyor ve o Delphi derleme ekibinde olduğu için bunun geçerli olduğuna inanıyorum :) Teşekkürler Barry.


1
Delphi 2006 yardımında bunu burada bulabilirsiniz: ms-help: //borland.bds4/bds4ref/html/Variables.htm "Bir global değişkeni açıkça başlatmazsanız, derleyici onu 0 olarak başlatır. Nesne örnek verisi ( alanları) da 0 olarak başlatılır. "
Giacomo Degli Esposti

"Buna inanmıyorum" yüzünden olumsuz oy verildi. Bu programlamadır, din değil. Ve Giacomo az önce gerçeği gösterdi.
InTheNameOfScience

6

Global değişkenler ve nesne örnek verileri (alanlar) her zaman sıfır olarak başlatılır. Prosedür ve yöntemlerdeki yerel değişkenler Win32 Delphi'de başlatılmaz; siz onlara kodda bir değer atayana kadar içerikleri tanımsız kalır.


5

Bir dil varsayılan başlatmalar sunsa bile, onlara güvenmeniz gerektiğine inanmıyorum. Bir değere başlangıç ​​yapmak, dildeki varsayılan başlatmaları bilmeyen ve derleyicilerdeki sorunları önleyen diğer geliştiriciler için çok daha açık hale getirir.


4
Tabi ki yapabilirsin. Ve yapmalısın. Her kurucuda her şeyi 0 / '' / false / nil olarak başlatmak gereksizdir. Öte yandan, küresel değişkenleri başlatmak o kadar da aptalca değil - bir kereliğine, başlatılıp başlatılmadıklarını asla hatırlayamıyorum (çünkü onları fazla kullanmıyorum).
gabr

2
Delphi, bir değişkeni ilan ettiğiniz noktada başlatmanıza izin verirse (örn. Var fObject: TObject = nil), bir değerle başlatmanın muhtemelen iyi bir fikir olduğunu kabul etmeye meyilli olurum. Ama bana göre bunu her nesne alanı için yapıcıda yapmak biraz fazla görünüyor.
MB.

4

Delphi 2007 yardım dosyasından:

ms-help: //borland.bds5/devcommon/variables_xml.html

"Bir genel değişkeni açıkça başlatmazsanız, derleyici onu 0 olarak başlatır."


3

Verilen cevaplarla ilgili küçük bir endişem var. Delphi, küresellerin ve yeni oluşturulan nesnelerin hafıza alanını sıfırlar. Bu NORMAL OLARAK başlatıldıkları anlamına gelse de olmadıkları bir durum vardır: belirli değerlerle numaralandırılmış türler. Ya sıfır yasal bir değer değilse?


1
Sıfır her zaman yasal bir değerdir, enum'un 1. değeridir. ord (MyFirstEnumValue) ile görebilirsiniz.
Francesca

Numaralandırılmış türdeki ilk değeri döndürür.
skamradt

6
Numaralandırmaya açıkça değerler atarsanız, sıfır her zaman geçerli bir değer değildir. Bu durumda, yine de 0 olarak başlatılır ve geçersiz bir değere sahipsiniz. Ancak numaralandırmalar normal tam sayı türleri üzerine boyanmış sözdizimsel şekerlerdir, bu nedenle bu gerçekten hiçbir şeyi bozmaz. Kodunuzun bununla başa çıkabileceğinden emin olun.
Mason Wheeler

2
@ François: TOneTwoThree = (One=1, Two=2, Three=3);
Numaralamanızı şöyle

0

Yeni eklenen (Delphi 10.3'ten beri) satır içi değişkenler, başlangıç ​​değerlerinin kontrolünü kolaylaştırmaktadır.

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.