Các biến delphi có được khởi tạo bằng một giá trị theo mặc định không?


103

Tôi mới sử dụng Delphi và tôi đã chạy một số thử nghiệm để xem biến đối tượng và biến ngăn xếp nào được khởi tạo theo mặc định:

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

Đây là hành vi tôi đã quen với các ngôn ngữ khác, nhưng tôi đang tự hỏi liệu có an toàn khi dựa vào nó trong Delphi không? Ví dụ: tôi đang tự hỏi liệu nó có thể phụ thuộc vào cài đặt trình biên dịch hay có thể hoạt động khác nhau trên các máy khác nhau hay không. Có bình thường không khi dựa vào các giá trị được khởi tạo mặc định cho các đối tượng, hay bạn đặt rõ ràng tất cả các biến phiên bản trong hàm tạo?

Đối với các biến ngăn xếp (cấp độ thủ tục), các thử nghiệm của tôi cho thấy rằng các boolean đơn nguyên là đúng, các số nguyên đơn nguyên là 2129993264 và các đối tượng không được phủ nhận chỉ là các con trỏ không hợp lệ (tức là không phải nil). Tôi đoán tiêu chuẩn là luôn đặt các biến mức thủ tục trước khi truy cập chúng?


3
Hai lưu ý: 1. Bản ghi không được khởi tạo. 2. Các biến đếm tham chiếu luôn được khởi tạo. !NHƯNG! trong một hàm trả về một chuỗi, 'Kết quả' không được khởi tạo thành chuỗi rỗng như bạn có thể mong đợi. Điều này là do 'Kết quả' không phải là var cục bộ. Vì vậy, luôn luôn làm: Kết quả: = '';
InTheNameOfScience,


Điều này có trả lời câu hỏi của bạn không? Những biến nào được khởi tạo khi ở Delphi?
InTheNameOfScience

Câu trả lời:


105

Có, đây là hành vi được ghi lại:

  • Các trường đối tượng luôn được khởi tạo thành 0, 0.0, '', False, nil hoặc bất cứ điều gì áp dụng.

  • Các biến toàn cục cũng luôn được khởi tạo thành 0, v.v.

  • Các biến * được đếm tham chiếu cục bộ luôn được khởi tạo bằng nil hoặc '';

  • Các biến cục bộ không được tính là tham chiếu * chưa được khởi tạo vì vậy bạn phải chỉ định một giá trị trước khi có thể sử dụng chúng.

Tôi nhớ rằng ở đâu đó Barry Kelly đã viết một định nghĩa cho "tính tham chiếu", nhưng không thể tìm thấy nó nữa, vì vậy điều này nên làm trong thời gian chờ đợi:

tham chiếu-đếm == tự được tính tham chiếu hoặc trực tiếp hoặc gián tiếp chứa các trường (đối với bản ghi) hoặc các phần tử (đối với mảng) được tính tham chiếu như: string, variant, interface hoặc mảng động hoặc mảng tĩnh chứa các loại như vậy.

Ghi chú:

  • record bản thân nó không đủ để trở thành tham chiếu được tính
  • Tôi chưa thử điều này với thuốc generic

2
Như Giacomo đã chỉ ra trong các nhận xét bên dưới, tất cả điều này được giải thích trong các tệp trợ giúp của Delphi tại ms-help: //borland.bds4/bds4ref/html/Variables.htm. Trong Delphi 2009, tôi đã tìm thấy thông tin tương tự bằng cách tìm kiếm trợ giúp cho các "biến" (thật thú vị là tôi đã thử rất nhiều tìm kiếm nhưng tôi không nghĩ nên thử cái đó).
MB.

8
Các biến cục bộ ĐƯỢC khởi tạo ($ 0) nếu chúng thuộc loại được quản lý như chuỗi, giao diện, mảng động hoặc các biến thể
Francesca

5
Tuy nhiên, có một ngoại lệ! Khi bạn ghi đè hàm tạo và không gọi hàm tạo kế thừa, có khả năng một số trường kết thúc không được khởi tạo! (Đặc biệt là với các phiên bản Delphi cũ hơn.) Vì TObject.Create chịu trách nhiệm xóa tất cả dữ liệu, không gọi dữ liệu đó dẫn đến có thể có dữ liệu không xác định.
Wim ten Brink

18
@WimtenBrink Tôi nghĩ bạn đã nhầm. Việc khởi tạo không được thực hiện bên trong TObject.Create, đó là một phương thức void, nhưng trong class function TObject.InitInstance(Instance: Pointer): TObject;đó LUÔN LUÔN được gọi trước bất kỳ lệnh gọi hàm tạo nào, ngay cả đối với các phiên bản Delphi cũ hơn. Nhận xét của bạn IMHO là sai và khó hiểu.
Arnaud Bouchez

7
Đừng quên rằng trong một hàm trả về một chuỗi, 'Kết quả' không được khởi tạo thành chuỗi trống như bạn có thể mong đợi. Điều này là do 'Kết quả' không phải là var cục bộ.
InTheNameOfScience

27

Các biến toàn cục không có bộ khởi tạo rõ ràng được cấp phát trong phần BSS trong tệp thực thi. Chúng không thực sự chiếm bất kỳ không gian nào trong EXE; phần BSS là một phần đặc biệt mà OS phân bổ và xóa bằng 0. Trên các hệ điều hành khác, cũng có cơ chế tương tự.

Bạn có thể phụ thuộc vào các biến toàn cục được khởi tạo bằng 0.


21

Các trường lớp mặc định là 0. Đây là tài liệu để bạn có thể dựa vào đó. Các khả biến của ngăn xếp cục bộ là không xác định trừ khi chuỗi hoặc giao diện, chúng được đặt thành 0.


Cảm ơn. "Số không" làm tôi bối rối một chút - điều đó có nghĩa là các chuỗi là '', và các giao diện là số không?
MB.

4
Vâng, chính xác là như vậy. nil = 0 (ở cấp trình hợp dịch) và '' = nil (quy ước Delphi).
gabr 25/09/08

1
"trừ khi chuỗi hoặc giao diện" không phải là mô tả hoàn chỉnh về thực tế. Ví dụ, mảng động cũng được khởi tạo. Nói chung hơn, quy tắc là các biến của loại được quản lý (được tính là tham chiếu) được khởi tạo, ngay cả khi là cục bộ.
Andreas Rejbrand

16

Chỉ là một lưu ý phụ (vì bạn mới sử dụng Delphi): Các biến toàn cục có thể được khởi tạo trực tiếp khi khai báo chúng:

var myGlobal:integer=99;

2
Vì 10.3 cũng áp dụng tương tự cho các biến cục bộ
Edijs Kolesnikovičs

1
Và nếu không được thực hiện một cách rõ ràng, họ đang khởi tạo 0, 0.0, False, nil, [], vv
Andreas Rejbrand

7

Đây là một trích dẫn của Ray Lischners Delphi trong một chương 2 Nutshell

"Khi Delphi lần đầu tiên tạo một đối tượng, tất cả các trường bắt đầu trống, nghĩa là, con trỏ được khởi tạo thành nil, chuỗi và mảng động trống, các số có giá trị 0, trường Boolean là Sai và Các biến được đặt thành Chưa được gán. (Xem NewInstance và InitInstance trong Chương 5 để biết thêm chi tiết.) "

Đúng là các biến cục bộ trong phạm vi cần được khởi tạo ... Tôi sẽ coi nhận xét ở trên rằng "Các biến toàn cục được khởi tạo" là không rõ ràng cho đến khi được cung cấp một tham chiếu - Tôi không tin điều đó.

chỉnh sửa ... Barry Kelly nói rằng bạn có thể phụ thuộc vào việc chúng được khởi tạo bằng 0, và vì anh ấy thuộc nhóm biên dịch Delphi nên tôi tin rằng điều đó là đúng :) Cảm ơn Barry.


1
Trong phần trợ giúp delphi 2006, bạn có thể tìm thấy nó ở đây: ms-help: //borland.bds4/bds4ref/html/Variables.htm "Nếu bạn không khởi tạo biến toàn cục một cách rõ ràng, trình biên dịch sẽ khởi tạo nó thành 0. Dữ liệu cá thể đối tượng ( các trường) cũng được khởi tạo thành 0. "
Giacomo Degli Esposti.

Bị từ chối vì "Tôi không tin điều đó". Đây là lập trình, không phải tôn giáo. Và Giacomo vừa chứng minh sự thật.
InTheNameOfScience

6

Các biến toàn cục và dữ liệu cá thể đối tượng (trường) luôn được khởi tạo bằng 0. Các biến cục bộ trong các thủ tục và phương thức không được khởi tạo trong Win32 Delphi; nội dung của chúng không được xác định cho đến khi bạn gán cho chúng một giá trị trong mã.


5

Ngay cả khi một ngôn ngữ cung cấp các khởi tạo mặc định, tôi không tin rằng bạn nên dựa vào chúng. Việc khởi tạo thành một giá trị làm cho nó trở nên rõ ràng hơn nhiều đối với các nhà phát triển khác, những người có thể không biết về các khởi tạo mặc định trong ngôn ngữ và ngăn ngừa các sự cố trên các trình biên dịch.


4
Tất nhiên bạn có thể. Và bạn nên. Việc khởi tạo mọi thứ thành 0 / '' / false / nil trong mọi hàm tạo là không cần thiết. Mặt khác, việc khởi tạo các biến toàn cục không phải là quá ngu ngốc - tôi không bao giờ có thể nhớ được liệu chúng có được khởi tạo hay không (vì tôi không sử dụng chúng nhiều).
gabr 25/09/08

2
Nếu Delphi cho phép bạn khởi tạo một biến tại cùng thời điểm khi bạn khai báo nó (ví dụ: var fObject: TObject = nil), tôi sẽ có xu hướng đồng ý rằng khởi tạo thành một giá trị có lẽ là một ý kiến ​​hay. Nhưng đối với tôi, có vẻ hơi nhiều để làm điều đó trong hàm tạo cho mọi trường đối tượng.
MB.

4

Từ tệp trợ giúp Delphi 2007:

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

"Nếu bạn không khởi tạo biến toàn cục một cách rõ ràng, trình biên dịch sẽ khởi tạo biến đó thành 0."


3

Tôi có một chút hiểu biết với các câu trả lời được đưa ra. Delphi xóa không gian bộ nhớ của các hình cầu và các đối tượng mới được tạo. Mặc dù điều này BÌNH THƯỜNG có nghĩa là chúng được khởi tạo nhưng có một trường hợp không phải là: các kiểu liệt kê với các giá trị cụ thể. Nếu số 0 không phải là giá trị pháp lý thì sao ??


1
Số không luôn là một giá trị pháp lý, nó là giá trị đầu tiên của enum. bạn có thể thấy nó với ord (MyFirstEnumValue).
Francesca 25-08

Nó sẽ trả về giá trị đầu tiên trong kiểu liệt kê.
skamradt 25/09/08

6
Số 0 không phải lúc nào cũng có giá trị pháp lý nếu bạn gán giá trị rõ ràng cho enum. Trong trường hợp đó, nó vẫn được khởi tạo bằng 0 và bạn có một giá trị không hợp lệ. Nhưng enums chỉ là đường cú pháp được vẽ trên các kiểu số nguyên bình thường, vì vậy điều này không thực sự phá vỡ bất cứ điều gì. Đảm bảo rằng mã của bạn có thể đối phó với nó.
Mason Wheeler

2
@ François: Không phải nếu bạn định nghĩa enum của mình như thế này:TOneTwoThree = (One=1, Two=2, Three=3);
fnkr 10/02/16

0

Các biến nội tuyến mới được giới thiệu (kể từ Delphi 10.3) đang làm cho việc kiểm soát các giá trị ban đầu dễ dàng hơn.

procedure TestInlineVariable;
begin
  var index: Integer := 345;
  ShowMessage(index.ToString);
end;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.