ตัวแปรเดลฟายเริ่มต้นด้วยค่าตามค่าเริ่มต้นหรือไม่


103

ฉันเพิ่งเริ่มใช้ Delphi และฉันได้ทำการทดสอบเพื่อดูว่าตัวแปรออบเจ็กต์และตัวแปรสแต็กใดบ้างที่เริ่มต้นโดยค่าเริ่มต้น:

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

นี่เป็นพฤติกรรมที่ฉันคุ้นเคยกับภาษาอื่น แต่ฉันสงสัยว่าจะปลอดภัยหรือไม่ที่จะพึ่งพาภาษาเดลฟี? ตัวอย่างเช่นฉันสงสัยว่าอาจขึ้นอยู่กับการตั้งค่าคอมไพเลอร์หรืออาจทำงานแตกต่างกันไปในเครื่องอื่น เป็นเรื่องปกติหรือไม่ที่จะใช้ค่าเริ่มต้นที่เป็นค่าเริ่มต้นสำหรับอ็อบเจ็กต์หรือคุณตั้งค่าตัวแปรอินสแตนซ์ทั้งหมดในคอนสตรัคเตอร์อย่างชัดเจน

สำหรับตัวแปรสแต็ก (ระดับขั้นตอน) การทดสอบของฉันแสดงให้เห็นว่าบูลีนที่มีการแปลงหน่วยเป็นจริงจำนวนเต็มหน่วยคือ 2129993264 และวัตถุที่ไม่ได้กำหนดค่าเริ่มต้นเป็นเพียงตัวชี้ที่ไม่ถูกต้อง (เช่นไม่ใช่ศูนย์) ฉันเดาว่าบรรทัดฐานคือต้องตั้งค่าตัวแปรระดับขั้นตอนก่อนเข้าถึงเสมอหรือไม่?


3
หมายเหตุสองประการ: 1. ไม่ได้เตรียมข้อมูลเบื้องต้น 2. ตัวแปรที่นับการอ้างอิงจะเริ่มต้นเสมอ !แต่! ในฟังก์ชันที่ส่งคืนสตริง 'ผลลัพธ์' จะไม่เริ่มต้นเป็นสตริงว่างอย่างที่คุณคาดหวัง เนื่องจาก 'ผลลัพธ์' ไม่ใช่ตัวแปรท้องถิ่น ดังนั้นให้ทำเสมอ: ผลลัพธ์: = '';
InTheNameOfScience


สิ่งนี้ตอบคำถามของคุณหรือไม่? ตัวแปรใดบ้างที่เริ่มต้นเมื่ออยู่ใน Delphi
InTheNameOfScience

คำตอบ:


106

ใช่นี่คือพฤติกรรมที่บันทึกไว้:

  • ฟิลด์ออบเจ็กต์จะเริ่มต้นเป็น 0, 0.0, '', False, nil หรืออะไรก็ตามที่ใช้เสมอ

  • ตัวแปรส่วนกลางจะเริ่มต้นเป็น 0 ฯลฯ เช่นกัน

  • ตัวแปรที่นับการอ้างอิงภายในเครื่องจะถูกกำหนดค่าเริ่มต้นเป็นศูนย์หรือ '';

  • ตัวแปรภายในที่ไม่นับการอ้างอิง * จะไม่ได้เริ่มต้นดังนั้นคุณต้องกำหนดค่าก่อนจึงจะใช้งานได้

ฉันจำได้ว่าBarry Kelly มีบางแห่งเขียนคำจำกัดความสำหรับ "การนับการอ้างอิง" แต่ไม่พบอีกต่อไปดังนั้นสิ่งนี้ควรทำในระหว่างนี้:

reference-count == ที่นับการอ้างอิงเองหรือโดยตรงหรือโดยอ้อมประกอบด้วยฟิลด์ (สำหรับระเบียน) หรือองค์ประกอบ (สำหรับอาร์เรย์) ที่มีการอ้างอิงเช่น: string, variant, interface หรืออาร์เรย์แบบไดนามิกหรืออาร์เรย์แบบคงที่ที่มีประเภทดังกล่าว

หมายเหตุ:

  • record ตัวเองไม่เพียงพอที่จะนับอ้างอิง
  • ฉันยังไม่ได้ลองสิ่งนี้กับยาชื่อสามัญ

2
ตามที่ Giacomo ได้ระบุไว้ในความคิดเห็นด้านล่างนี้มีคำอธิบายทั้งหมดในไฟล์วิธีใช้ Delphi ที่ ms-help: //borland.bds4/bds4ref/html/Variables.htm ใน Delphi 2009 ฉันพบข้อมูลเดียวกันโดยค้นหาความช่วยเหลือสำหรับ "ตัวแปร" (น่าสนุกพอสมควรฉันลองค้นหาหลายครั้ง แต่ไม่คิดจะลองใช้)
.

8
ตัวแปรโลคัลเริ่มต้น ($ 0) หากเป็นประเภทที่มีการจัดการเช่นสตริงอินเทอร์เฟซอาร์เรย์แบบไดนามิกหรือตัวแปร
Francesca

5
มีข้อยกเว้น! เมื่อคุณแทนที่ตัวสร้างและไม่เรียกตัวสร้างที่สืบทอดมามีโอกาสที่บางฟิลด์จะจบลงโดยไม่ได้เริ่มต้น! (โดยเฉพาะอย่างยิ่งกับ Delphi เวอร์ชันเก่า ๆ ) เนื่องจาก TObject.Create มีหน้าที่รับผิดชอบในการทำให้ข้อมูลทั้งหมดเป็นศูนย์ไม่ใช่การเรียกข้อมูลนั้นส่งผลให้เกิดข้อมูลที่ไม่รู้จักที่เป็นไปได้
Wim ten Brink

18
@WimtenBrink ฉันคิดว่าคุณคิดผิด การกำหนดค่าเริ่มต้นไม่ได้ทำภายในTObject.Createซึ่งเป็นวิธีที่เป็นโมฆะ แต่class function TObject.InitInstance(Instance: Pointer): TObject;จะเรียกใช้เสมอก่อนการเรียกตัวสร้างใด ๆ แม้กระทั่งสำหรับเดลฟีเวอร์ชันเก่า ความคิดเห็นของคุณคือ IMHO ผิดและสับสน
Arnaud Bouchez

7
อย่าลืมว่าในฟังก์ชันที่ส่งคืนสตริง 'ผลลัพธ์' จะไม่เริ่มต้นเป็นสตริงว่างอย่างที่คุณคาดหวัง เนื่องจาก 'ผลลัพธ์' ไม่ใช่ตัวแปรท้องถิ่น
InTheNameOfScience

27

ตัวแปรส่วนกลางที่ไม่มีตัวเริ่มต้นอย่างชัดเจนจะถูกจัดสรรในส่วน BSS ในไฟล์ปฏิบัติการ พวกเขาไม่ได้ใช้พื้นที่ใด ๆ ใน EXE ส่วน BSS เป็นส่วนพิเศษที่ระบบปฏิบัติการจัดสรรและล้างเป็นศูนย์ บนระบบปฏิบัติการอื่นมีกลไกที่คล้ายกัน

คุณสามารถขึ้นอยู่กับตัวแปรส่วนกลางที่เริ่มต้นเป็นศูนย์


21

ฟิลด์คลาสเป็นศูนย์เริ่มต้น นี่เป็นเอกสารเพื่อให้คุณวางใจได้ โลคัลสแต็ก varaiables ไม่ได้กำหนดเว้นแต่สตริงหรืออินเทอร์เฟซสิ่งเหล่านี้ถูกตั้งค่าเป็นศูนย์


ขอบคุณ. "Zero" ทำให้ฉันสับสนนิดหน่อยนั่นหมายความว่าสตริงเป็น '' และอินเทอร์เฟซเป็นศูนย์หรือไม่?
.

4
ใช่แน่นอน ศูนย์ = 0 (ที่ระดับแอสเซมเบลอร์) และ '' = ศูนย์ (อนุสัญญาเดลฟี)
gabr

1
"เว้นแต่สตริงหรืออินเทอร์เฟซ" ไม่ใช่คำอธิบายที่สมบูรณ์ของความเป็นจริง ตัวอย่างเช่นอาร์เรย์แบบไดนามิกจะเริ่มต้นด้วย โดยทั่วไปกฎคือตัวแปรของประเภทที่มีการจัดการ (การนับการอ้างอิง) จะเริ่มต้นแม้ว่าจะเป็นแบบโลคัลก็ตาม
Andreas Rejbrand

16

เช่นเดียวกับหมายเหตุด้านข้าง (เนื่องจากคุณยังใหม่กับ Delphi): ตัวแปรส่วนกลางสามารถเริ่มต้นได้โดยตรงเมื่อประกาศ:

var myGlobal:integer=99;

2
เนื่องจาก 10.3 ใช้กับตัวแปรท้องถิ่นเช่นเดียวกัน
Edijs Kolesnikovič

1
และหากไม่ได้ดำเนินการอย่างชัดเจนพวกเขาจะเริ่มต้นเป็น 0, 0.0, False, nil, [] ฯลฯ
Andreas Rejbrand

7

นี่คือคำพูดจาก Ray Lischners Delphi ในบทสรุป2

"เมื่อเดลฟีสร้างออบเจ็กต์ครั้งแรกฟิลด์ทั้งหมดจะเริ่มว่างเปล่านั่นคือพอยน์เตอร์จะเริ่มต้นเป็นศูนย์สตริงและอาร์เรย์แบบไดนามิกว่างเปล่าตัวเลขมีค่าเป็นศูนย์ฟิลด์บูลีนเป็นเท็จและตัวแปรจะถูกตั้งค่าเป็นไม่กำหนด (ดู NewInstance และ InitInstance ในบทที่ 5 สำหรับรายละเอียด) "

เป็นเรื่องจริงที่ต้องเริ่มต้นตัวแปรภายในขอบเขต ... ฉันจะปฏิบัติต่อความคิดเห็นข้างต้นว่า "ตัวแปรทั่วโลกเริ่มต้นแล้ว" เป็นที่น่าสงสัยจนกว่าจะมีการอ้างอิง - ฉันไม่เชื่อเช่นนั้น

แก้ไข ... Barry Kelly กล่าวว่าคุณสามารถพึ่งพาพวกเขาได้ว่าเป็นศูนย์เริ่มต้นและเนื่องจากเขาอยู่ในทีมคอมไพเลอร์ Delphi ฉันเชื่อว่านั่นคือ :) ขอบคุณ Barry


1
ใน delphi 2006 คุณสามารถค้นหาได้ที่นี่: ms-help: //borland.bds4/bds4ref/html/Variables.htm "ถ้าคุณไม่ได้เตรียมใช้งานตัวแปรส่วนกลางอย่างชัดเจนคอมไพลเลอร์จะเริ่มต้นเป็น 0 ข้อมูลอินสแตนซ์ออบเจ็กต์ ( ฟิลด์) จะเริ่มต้นเป็น 0 ด้วย "
Giacomo Degli Esposti

ถูกลดคะแนนเนื่องจาก "ฉันไม่เชื่ออย่างนั้น" นี่คือการเขียนโปรแกรมไม่ใช่ศาสนา และ Giacomo ก็แสดงให้เห็นถึงความจริง
InTheNameOfScience

6

ตัวแปรส่วนกลางและข้อมูลอินสแตนซ์ออบเจ็กต์ (ฟิลด์) จะเริ่มต้นเป็นศูนย์เสมอ ตัวแปรโลคัลในโพรซีเดอร์และวิธีการไม่ได้ถูกเตรียมใช้งานใน Win32 Delphi เนื้อหาของพวกเขาไม่ได้กำหนดไว้จนกว่าคุณจะกำหนดค่าในโค้ด


5

แม้ว่าภาษาจะเสนอการเริ่มต้นเริ่มต้น แต่ฉันไม่เชื่อว่าคุณควรพึ่งพาภาษาเหล่านี้ การเริ่มต้นเป็นค่าทำให้นักพัฒนาอื่น ๆ ที่อาจไม่ทราบเกี่ยวกับการกำหนดค่าเริ่มต้นในภาษาได้ชัดเจนขึ้นและป้องกันปัญหาในคอมไพเลอร์


4
แน่นอนคุณสามารถ. และคุณควร การเริ่มต้นทุกอย่างเป็น 0 / '' / false / nil ในทุกตัวสร้างนั้นไม่จำเป็น ในทางกลับกันการเริ่มต้นตัวแปรส่วนกลางไม่ใช่เรื่องที่โง่เขลา - ครั้งหนึ่งฉันไม่สามารถจำได้ว่ามีการเริ่มต้นหรือไม่ (เนื่องจากฉันไม่ได้ใช้มันมากนัก)
gabr

2
หาก Delphi ให้คุณเริ่มต้นตัวแปร ณ จุดเดียวกับที่คุณประกาศ (เช่น var fObject: TObject = nil) ฉันมีแนวโน้มที่จะยอมรับว่าการเริ่มต้นเป็นค่าอาจเป็นความคิดที่ดี แต่สำหรับฉันแล้วดูเหมือนว่าจะต้องทำในตัวสร้างสำหรับทุกช่องวัตถุ
.

4

จากไฟล์วิธีใช้ Delphi 2007:

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

"ถ้าคุณไม่ได้เตรียมใช้งานตัวแปรส่วนกลางอย่างชัดเจนคอมไพเลอร์จะเริ่มต้นเป็น 0"


3

ฉันมีความเข้าใจเล็กน้อยกับคำตอบที่ได้รับ เดลฟีศูนย์ออกจากพื้นที่หน่วยความจำของโลกและวัตถุที่สร้างขึ้นใหม่ แม้ว่าปกติจะหมายความว่ามีการเริ่มต้น แต่ก็มีกรณีหนึ่งที่ไม่ได้ระบุประเภทที่มีค่าเฉพาะ จะเกิดอะไรขึ้นถ้าศูนย์ไม่ใช่ค่าทางกฎหมาย ??


1
ศูนย์เป็นค่าทางกฎหมายเสมอเป็นค่าที่ 1 ของ enum คุณสามารถดูได้ด้วย ord (MyFirstEnumValue)
Francesca

มันจะส่งคืนค่าแรกในประเภทที่แจกแจง
skamradt

6
ศูนย์ไม่ใช่ค่าทางกฎหมายเสมอไปหากคุณกำหนดค่าให้กับ enum อย่างชัดเจน ในกรณีนี้ค่านี้ยังคงเริ่มต้นเป็น 0 และคุณมีค่าที่ไม่ถูกต้อง แต่ enums เป็นเพียงแค่น้ำตาลในรูปแบบที่ถูกวาดทับด้วยจำนวนเต็มปกติดังนั้นจึงไม่ได้ทำลายอะไรเลย ตรวจสอบให้แน่ใจว่ารหัสของคุณสามารถจัดการกับมันได้
Mason Wheeler

2
@ François: ไม่ใช่ถ้าคุณกำหนด enum ของคุณแบบนี้TOneTwoThree = (One=1, Two=2, Three=3);
fnkr

0

เพิ่งเปิดตัว (ตั้งแต่ Delphi 10.3) ตัวแปรอินไลน์ทำให้การควบคุมค่าเริ่มต้นง่ายขึ้น

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.