Apakah variabel delphi diinisialisasi dengan nilai secara default?

103

Saya baru mengenal Delphi, dan saya telah menjalankan beberapa tes untuk melihat variabel objek dan variabel tumpukan apa yang diinisialisasi secara default:

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

Ini adalah perilaku yang biasa saya lakukan dari bahasa lain, tetapi saya bertanya-tanya apakah aman untuk mengandalkannya di Delphi? Misalnya, saya bertanya-tanya apakah itu mungkin bergantung pada pengaturan kompiler, atau mungkin bekerja secara berbeda pada mesin yang berbeda. Apakah normal untuk mengandalkan nilai default yang diinisialisasi untuk objek, atau apakah Anda secara eksplisit menyetel semua variabel instance dalam konstruktor?

Sedangkan untuk variabel stack (procedure-level), pengujian saya menunjukkan bahwa boolean yang disatukan adalah benar, integer yang disatukan adalah 2129993264, dan objek yang tidak terinialisasi hanyalah pointer yang tidak valid (yaitu tidak nihil). Saya menduga normanya adalah selalu menetapkan variabel tingkat prosedur sebelum mengaksesnya?

MB.
sumber
3
Dua catatan: 1. Rekaman tidak diinisialisasi. 2. Variabel terhitung referensi selalu diinisialisasi. !TAPI! dalam fungsi yang mengembalikan string, 'Hasil' tidak diinisialisasi ke string kosong seperti yang Anda harapkan. Ini karena 'Hasil' bukan var lokal. Jadi, selalu lakukan: Hasil: = '';
InTheNameOfScience
Apakah ini menjawab pertanyaan Anda? Variabel mana yang diinisialisasi saat di Delphi?
InTheNameOfScience

Jawaban:

105

Ya, ini adalah perilaku yang didokumentasikan:

  • Bidang objek selalu diinisialisasi ke 0, 0.0, '', False, nil atau apa pun yang berlaku.

  • Variabel global selalu diinisialisasi ke 0 dll juga;

  • Variabel yang dihitung oleh referensi lokal * selalu diinisialisasi menjadi nol atau '';

  • Variabel lokal yang tidak dihitung referensi * * tidak diinisialisasi sehingga Anda harus menetapkan nilai sebelum dapat menggunakannya.

Saya ingat Barry Kelly di suatu tempat menulis definisi untuk "referensi-dihitung", tetapi tidak dapat menemukannya lagi, jadi ini harus dilakukan untuk sementara:

reference-counted == yang referensi-menghitungnya sendiri, atau secara langsung atau tidak langsung berisi bidang (untuk rekaman) atau elemen (untuk array) yang dihitung referensi seperti: string, variant, interface atau array dinamis atau array statis yang berisi tipe seperti itu.

Catatan:

  • record itu sendiri tidak cukup untuk menjadi referensi yang dihitung
  • Saya belum mencoba ini dengan obat generik
Giacomo Degli Esposti
sumber
2
Seperti yang ditunjukkan Giacomo pada komentar di bawah, ini semua dijelaskan dalam file bantuan Delphi di ms-help: //borland.bds4/bds4ref/html/Variables.htm. Dalam Delphi 2009 saya menemukan info yang sama dengan mencari bantuan untuk "variabel" (lucunya saya mencoba banyak pencarian tetapi saya tidak berpikir untuk mencobanya).
MB.
8
Variabel lokal DIinisialisasi ($ 0) jika mereka adalah jenis yang dikelola seperti string, antarmuka, larik dinamis, atau varian
Francesca
5
Namun, ada pengecualian! Saat Anda mengganti konstruktor, dan tidak memanggil konstruktor yang diwariskan, ada kemungkinan beberapa bidang tidak diinisialisasi! (Terutama dengan versi Delphi yang lebih lama.) Karena TObject.Create bertanggung jawab untuk membidik semua data, tidak memanggil yang satu itu menghasilkan kemungkinan data yang tidak diketahui.
Wim ten Brink
18
@WimtenBrink Saya pikir Anda salah. Inisialisasi tidak dilakukan di dalam TObject.Create, yang merupakan metode void, tetapi class function TObject.InitInstance(Instance: Pointer): TObject;SELALU dipanggil sebelum panggilan konstruktor, bahkan untuk versi Delphi yang lebih lama. Komentar Anda salah IMHO dan membingungkan.
Arnaud Bouchez
7
Jangan lupa bahwa dalam fungsi yang mengembalikan string, 'Hasil' tidak diinisialisasi menjadi string kosong seperti yang Anda harapkan. Ini karena 'Hasil' bukan var lokal.
InTheNameOfScience
27

Variabel global yang tidak memiliki penginisialisasi eksplisit dialokasikan di bagian BSS di file yang dapat dieksekusi. Mereka tidak benar-benar mengambil ruang apa pun di EXE; bagian BSS adalah bagian khusus yang dialokasikan oleh OS dan dihapus ke nol. Di sistem operasi lain, ada mekanisme serupa.

Anda dapat bergantung pada variabel global yang diinisialisasi nol.

Barry Kelly
sumber
21

Bidang kelas default nol. Ini didokumentasikan sehingga Anda dapat mengandalkannya. Variabel tumpukan lokal tidak ditentukan kecuali string atau antarmuka, ini disetel ke nol.

Martin Liesén
sumber
Terima kasih. "Nol" agak membingungkan saya - apakah itu berarti string adalah '', dan antarmuka nihil?
MB.
4
Ya, persis seperti itu. nil = 0 (pada tingkat assembler) dan '' = nil (konvensi Delphi).
gabr
1
"kecuali string atau antarmuka" bukanlah deskripsi lengkap tentang realitas. Array dinamis, misalnya, juga diinisialisasi. Secara lebih umum, aturannya adalah variabel jenis terkelola (dihitung referensi) diinisialisasi, meskipun bersifat lokal.
Andreas Rejbrand
16

Sebagai catatan tambahan (karena Anda baru mengenal Delphi): Variabel global dapat diinisialisasi secara langsung saat mendeklarasikannya:

var myGlobal:integer=99;
Heinrich Ulbricht
sumber
2
Sejak 10,3 yang sama berlaku untuk variabel lokal
Edijs Kolesnikovičs
1
Dan jika tidak dilakukan secara eksplisit, mereka diinisialisasi ke 0, 0.0, False, nil, [], dll.
Andreas Rejbrand
7

Berikut kutipan dari Ray Lischners Delphi in a Nutshell Bab 2

"Saat Delphi pertama kali membuat objek, semua bidang mulai kosong, yaitu, pointer diinisialisasi ke nol, string dan larik dinamis kosong, angka memiliki nilai nol, bidang Boolean False, dan Varian disetel ke Tidak ditetapkan. (Lihat NewInstance dan InitInstance di Bab 5 untuk detailnya.) "

Memang benar bahwa variabel dalam lingkup lokal perlu diinisialisasi ... Saya akan menganggap komentar di atas bahwa "Variabel global diinisialisasi" sebagai meragukan sampai diberikan referensi - Saya tidak percaya itu.

sunting ... Barry Kelly mengatakan Anda dapat bergantung pada mereka yang diinisialisasi nol, dan karena dia berada di tim penyusun Delphi, saya yakin itu berlaku :) Terima kasih Barry.

Drew Gibson
sumber
1
Di delphi 2006 bantuan Anda dapat menemukannya di sini: ms-help: //borland.bds4/bds4ref/html/Variables.htm "Jika Anda tidak secara eksplisit menginisialisasi variabel global, kompilator menginisialisasi ke 0. Data instance objek ( bidang) juga diinisialisasi ke 0. "
Giacomo Degli Esposti
Tidak disukai karena "Saya tidak percaya itu". Ini adalah pemrograman, bukan agama. Dan Giacomo baru saja menunjukkan kebenarannya.
InTheNameOfScience
6

Variabel global dan data contoh objek (bidang) selalu diinisialisasi ke nol. Variabel lokal dalam prosedur dan metode tidak diinisialisasi di Win32 Delphi; isinya tidak terdefinisi sampai Anda menetapkan nilai dalam kode.

Ondrej Kelle
sumber
5

Meskipun suatu bahasa memang menawarkan inisialisasi default, saya tidak yakin Anda harus mengandalkannya. Menginisialisasi suatu nilai membuatnya lebih jelas bagi pengembang lain yang mungkin tidak tahu tentang inisialisasi default dalam bahasa dan mencegah masalah di seluruh kompiler.

Thomas Owens
sumber
4
Tentu saja Anda bisa. Dan Anda harus melakukannya. Menginisialisasi semuanya ke 0 / '' / false / nil di setiap konstruktor tidak perlu. Menginisialisasi variabel global, di sisi lain, tidak begitu bodoh - saya tidak pernah ingat apakah mereka diinisialisasi atau tidak (karena saya tidak banyak menggunakannya).
gabr
2
Jika Delphi membiarkan Anda menginisialisasi variabel pada titik yang sama dengan saat Anda mendeklarasikannya (misalnya var fObject: TObject = nil) saya akan cenderung setuju bahwa menginisialisasi nilai mungkin adalah ide yang bagus. Tetapi bagi saya tampaknya sedikit banyak melakukannya di konstruktor untuk setiap bidang objek.
MB.
4

Dari file bantuan Delphi 2007:

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

"Jika Anda tidak secara eksplisit menginisialisasi variabel global, compiler akan menginisialisasi ke 0."

Ondrej Kelle
sumber
3

Saya memiliki sedikit keluhan dengan jawaban yang diberikan. Delphi mengosongkan ruang memori global dan objek yang baru dibuat. Meskipun ini secara NORMAL berarti mereka diinisialisasi, ada satu kasus di mana mereka tidak: tipe yang disebutkan dengan nilai tertentu. Bagaimana jika nol bukanlah nilai hukum ??

Loren Pechtel
sumber
1
Nol selalu merupakan nilai hukum, ini adalah nilai pertama dari enum. Anda dapat melihatnya dengan ord (MyFirstEnumValue).
Francesca
Ini akan mengembalikan nilai pertama dalam tipe enumerasi.
skamradt
6
Nol tidak selalu merupakan nilai legal jika Anda secara eksplisit menetapkan nilai ke enum. Jika demikian, ini masih diinisialisasi ke 0, dan Anda memiliki nilai ilegal. Tapi enum hanyalah gula sintaksis yang dilukis di atas tipe bilangan bulat normal, jadi ini tidak benar-benar merusak apa pun. Pastikan kode Anda bisa mengatasinya.
Mason Wheeler
2
@ François: Tidak jika Anda menentukan enum seperti ini:TOneTwoThree = (One=1, Two=2, Three=3);
fnkr
0

Variabel sebaris yang baru diperkenalkan (sejak Delphi 10.3) membuat kontrol nilai awal lebih mudah.

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
Jacek Krawczyk
sumber