2009-12-09 17 views
14

một số câu hỏi về các bản ghi trong Delphi:Đĩa hát trong Delphi

  1. Như hồ sơ được hầu như các lớp học, tại sao không chỉ sử dụng các lớp học thay vì hồ sơ?
  2. Về lý thuyết, bộ nhớ được cấp phát cho một bản ghi khi nó được khai báo bởi một biến; nhưng, và bộ nhớ được phát hành như thế nào sau?
  3. Tôi có thể hiểu được tiện ích của con trỏ để ghi vào một đối tượng danh sách, nhưng với Generics Containers (TList<T>), có cần phải sử dụng con trỏ chưa? nếu không, làm thế nào để xóa/phát hành mỗi bản ghi vào một Container chung? Nếu tôi muốn xóa một bản ghi cụ thể vào một Container chung, làm thế nào để làm điều đó?

Trả lời

10

Đối với 1 và 2: bản ghi là các loại giá trị, trong khi các lớp là loại tham chiếu. Chúng được phân bổ trên stack, hoặc trực tiếp trong không gian bộ nhớ của bất kỳ biến lớn hơn có chứa chúng, thay vì thông qua một con trỏ, và tự động làm sạch bởi trình biên dịch khi chúng đi ra khỏi phạm vi.

Còn đối với câu hỏi thứ ba của bạn, TList<TMyRecord> tuyên bố nội bộ array of TMyRecord cho dung lượng lưu trữ. Tất cả các bản ghi trong đó sẽ được dọn sạch khi danh sách bị hủy. Nếu bạn muốn xóa một phương thức cụ thể, hãy sử dụng phương thức Delete để xóa theo chỉ mục hoặc phương pháp Remove để tìm và xóa. Nhưng lưu ý rằng vì đó là một loại giá trị, mọi thứ bạn làm sẽ tạo bản sao của bản ghi, chứ không phải sao chép các tham chiếu đến nó.

+0

Cảm ơn ông Wheeler và một câu hỏi khác: Con trỏ để ghi = Lớp học? –

+1

Không, con trỏ để ghi = con trỏ để ghi. Một đối tượng (cá thể lớp) khác với một bản ghi theo nhiều cách. –

3

Có một vài khác biệt khác giữa một lớp và một bản ghi. Các lớp học có thể sử dụng polymorphism và hiển thị giao diện. Các bản ghi không thể thực thi các destructors (mặc dù kể từ khi Delphi 2006 chúng có thể thực hiện các hàm tạo và phương thức).

Bản ghi rất hữu ích trong phân đoạn bộ nhớ thành cấu trúc hợp lý hơn vì mục dữ liệu đầu tiên trong bản ghi nằm ở cùng một điểm địa chỉ của con trỏ với bản ghi. Đây không phải là trường hợp cho các lớp học.

+0

Ngoài ra, các bản ghi hỗ trợ quá tải toán tử, điều này có thể hữu ích trong một số trường hợp. –

19

Có rất nhiều sự khác biệt giữa các bản ghi và các lớp; và không có "Con trỏ để ghi" <> "Lớp". Mỗi người đều có ưu và nhược điểm riêng; một trong những điều quan trọng về phát triển phần mềm là hiểu những điều này để bạn có thể dễ dàng lựa chọn thích hợp nhất cho một tình huống nhất định.

  1. Câu hỏi này dựa trên tiền đề sai. Các bản ghi không giống như các lớp học, giống như cách mà các số nguyên không gần giống như Doubles.
    • Các lớp học phải luôn được khởi động động, trong khi đây là khả năng, nhưng không phải là yêu cầu đối với hồ sơ.
    • Các trường hợp của các lớp (mà chúng ta gọi là các đối tượng) luôn được truyền xung quanh bằng tham chiếu, có nghĩa là nhiều phần mã sẽ chia sẻ và hành động trên cùng một cá thể. Đây là điều quan trọng cần nhớ, bởi vì bạn có thể vô ý sửa đổi một đối tượng như là một tác dụng phụ; mặc dù khi được thực hiện cố ý, đó là một tính năng mạnh mẽ. Mặt khác, các bản ghi được truyền theo giá trị; bạn cần phải chỉ rõ một cách rõ ràng nếu bạn đang truyền chúng theo tham chiếu.
    • Các lớp học không 'sao chép dễ dàng như bản ghi'. Khi tôi nói sao chép, tôi có nghĩa là một trường hợp riêng biệt nhân bản một nguồn. (Điều này phải rõ ràng trong ánh sáng của giá trị/chú thích tham chiếu ở trên).
    • Bản ghi có xu hướng hoạt động rất tốt với các tệp đã nhập (vì chúng dễ dàng sao chép).
    • Bản ghi có thể che phủ các trường bằng các trường khác (trường hợp x// unions)
    • Đây là những nhận xét về lợi ích tình huống nhất định của hồ sơ; ngược lại, cũng có những lợi ích tình huống cho các lớp học mà tôi sẽ không giải thích.
  2. Có lẽ cách dễ nhất để hiểu điều này là có một chút nhỏ nhặt về nó. Hãy làm rõ; bộ nhớ không thực sự được cấp phát 'khi được khai báo', nó được cấp phát khi biến nằm trong phạm vi và được phân bổ khi nó nằm ngoài phạm vi. Vì vậy, đối với một biến địa phương, nó được phân bổ ngay trước khi bắt đầu thường trình, và deallocated ngay sau khi kết thúc. Đối với một trường lớp, nó được cấp phát khi đối tượng được tạo và được deallocated khi nó bị hủy.
  3. Một lần nữa, có những ưu và nhược điểm ...
    • Nó có thể chậm hơn và đòi hỏi nhiều bộ nhớ để sao chép toàn bộ hồ sơ (như với generics) hơn là chỉ cần sao chép các tài liệu tham khảo.
    • Truyền hồ sơ xung quanh bằng tham chiếu (sử dụng con trỏ) là một kỹ thuật mạnh mẽ nhờ đó bạn có thể dễ dàng sửa đổi bản sao của bản ghi. Nếu không có điều này, bạn phải vượt qua hồ sơ của bạn bằng giá trị (tức là sao chép nó) nhận được bản ghi thay đổi như là kết quả, sao chép nó một lần nữa để cấu trúc của riêng bạn.
  4. Con trỏ có ghi lại như lớp học không? Không hoàn toàn không. Chỉ hai sự khác biệt:
    • Các lớp hỗ trợ kế thừa đa hình.
    • Các lớp học có thể triển khai giao diện.
+0

Cảm ơn Marco vì đã thêm ghi chú về các bản ghi biến thể (sử dụng ca x của ...) –

9

Một trong những lợi ích chính của hồ sơ là khi bạn có "mảng bản ghi" lớn. Điều này được tạo ra trong bộ nhớ bằng cách phân bổ không gian cho tất cả các bản ghi trong một không gian RAM liền kề, cực kỳ nhanh. Nếu bạn đã sử dụng "mảng của TClass" thay vào đó, mỗi đối tượng trong mảng sẽ phải được phân bổ bởi chính nó, mà là chậm.

Đã có rất nhiều công việc để cải thiện tốc độ phân bổ bộ nhớ, để cải thiện tốc độ của chuỗi và đối tượng, nhưng nó sẽ không bao giờ nhanh như thay thế 100.000 cấp phát bộ nhớ với 1 cấp phát bộ nhớ.

Tuy nhiên, nếu bạn sử dụng mảng bản ghi, đừng sao chép bản ghi xung quanh trong các biến cục bộ. Điều đó có thể dễ dàng giết lợi ích tốc độ.

3

1) Để cho phép thừa kế và đa hình, các lớp học có một số chi phí. Hồ sơ không cho phép chúng, và trong một số trường hợp có thể hơi nhanh hơn và đơn giản hơn để sử dụng. Không giống như các lớp, luôn được phân bổ trong heap và được quản lý thông qua các tham chiếu, các bản ghi có thể được cấp phát trên stack, truy cập trực tiếp và gán cho nhau mà không cần phải gọi phương thức "Assign". Ngoài ra các bản ghi cũng hữu ích để truy cập các khối bộ nhớ với một cấu trúc nhất định, vì bố cục bộ nhớ của chúng chính xác như cách bạn định nghĩa nó. Bố cục bộ nhớ của cá thể lớp được điều khiển bởi trình biên dịch và có dữ liệu bổ sung để làm cho các đối tượng hoạt động (tức là con trỏ đến Bảng Phương pháp Ảo). Trừ khi bạn phân bổ các bản ghi động, sử dụng New() hoặc GetMem(), bộ nhớ của bản ghi được quản lý bởi trình biên dịch, các phao hoặc các mảng tĩnh: bộ nhớ biến toàn cục được cấp phát khi khởi động và phát hành khi chương trình kết thúc, và các biến cục bộ được cấp phát trên ngăn xếp nhập hàm/thủ tục/phương thức và thoát ra. Việc phân bổ/giải phóng bộ nhớ trong ngăn xếp nhanh hơn vì nó không yêu cầu các cuộc gọi đến trình quản lý bộ nhớ, nó chỉ là một vài hướng dẫn lắp ráp để thay đổi sổ đăng ký ngăn xếp.Nhưng lưu ý rằng việc phân bổ cấu trúc lớn trên ngăn xếp có thể gây ra tràn ngăn xếp, vì kích thước ngăn xếp tối đa được cố định và không phải là rất lớn (xem các tùy chọn trình liên kết). Nếu các bản ghi là các trường của một lớp, chúng được cấp phát khi lớp được tạo ra và được giải phóng khi lớp đó được giải phóng.

3) Một trong những ưu điểm của generics là loại bỏ nhu cầu quản lý con trỏ ở mức độ thấp - nhưng hãy lưu ý đến các hoạt động bên trong.