2010-11-19 59 views
9

Tôi muốn hiểu điều gì sẽ xảy ra khi kích thước của mảng động được tăng lên.Điều gì sẽ xảy ra khi tăng kích thước của mảng động?

hiểu biết của tôi cho đến nay:

  • phần tử mảng hiện tại sẽ không thay đổi.
  • Các phần tử mảng mới được khởi tạo thành 0
  • Tất cả các phần tử mảng liền kề nhau trong bộ nhớ.

Khi kích thước mảng tăng lên, bộ nhớ thừa sẽ được gắn vào khối bộ nhớ hiện có hay các phần tử hiện có sẽ được sao chép vào khối bộ nhớ hoàn toàn mới?

Việc thay đổi kích thước của mảng động có hậu quả cho con trỏ tham chiếu các phần tử mảng hiện có không?

Xin cảm ơn,

[sửa] Giả định không chính xác xảy ra. (Phần tử mảng mới được khởi tạo 0)

+0

[Tài liệu được thay đổi vào ngày 26 tháng 10] (http://docwiki.embarcadero.com/VCL/e/index.php?title=System.SetLength&diff=414648&oldid=411229), vì vậy mục đã bỏ qua của bạn hiện đã chính xác : "không gian được cấp phát mới được đặt thành 0 hoặc không". –

+0

Câu hỏi là phiên bản nào của Delphi đã được giới thiệu? Các tài liệu mà @Rob liên kết là cho Delphi XE, nhưng tôi có thể thấy các cuộc gọi FillChar (một Rob đề cập trong bình luận của mình để trả lời của tôi) trong DynArraySetLength thủ tục của D2009 là tốt ... –

+0

Mới được phân bổ không gian đã thực sự được khởi tạo đến 0 hoặc không bằng 0 từ D5 trên (đó là những gì tôi có thể dễ dàng kiểm tra). Xem cập nhật cho câu trả lời của tôi. Và có lẽ kể từ khi giới thiệu mảng động như @ David nhận xét về câu trả lời của tôi. –

Trả lời

10
  • phần tử mảng hiện tại sẽ vẫn không thay đổi:
  • phần tử mảng mới được khởi tạo 0: (xem cập nhật) không, trừ khi nó là một mảng các loại được quản lý bởi trình biên dịch như chuỗi, một mảng khác hoặc một biến thể
  • Tất cả các phần tử mảng liền kề nhau trong bộ nhớ: yes

Khi kích thước mảng là tăng, mảng sẽ sao chép. Từ tài liệu: ... bộ nhớ cho mảng động được phân bổ lại khi bạn chỉ định một giá trị cho mảng hoặc chuyển nó tới thủ tục SetLength.

Vì vậy, , tăng kích thước mảng động không có hậu quả cho con trỏ tham chiếu các phần tử mảng hiện có.

Nếu bạn muốn giữ tham chiếu đến các thành phần hiện có, hãy sử dụng chỉ mục của chúng trong mảng (dựa trên 0).

Cập nhật

Comments bởi Rob và David nhắc tôi để kiểm tra việc khởi tạo mảng động trong Delphi5 (như tôi có mà sẵn anyway). Trước tiên, hãy sử dụng một số mã để tạo các loại mảng động khác nhau và kiểm tra chúng trong trình gỡ lỗi. Tất cả chúng đều được khởi tạo đúng cách, nhưng đó vẫn có thể là kết quả trước khi khởi tạo vị trí bộ nhớ nơi chúng được cấp phát. Vì vậy, kiểm tra RTL. Hóa ra D5 đã có báo cáo kết quả FillChar trong phương pháp DynArraySetLength rằng Rob chỉ ra:

// Set the new memory to all zero bits 
    FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0); 
+0

Cảm ơn Marjan. Tôi cần phải suy nghĩ lại việc triển khai danh sách liên kết đôi của mình. – Shannon

+0

Trong triển khai hiện tại, các phần tử mảng mới ** được ** khởi tạo về 0. Đó chỉ là một chi tiết thực hiện, mặc dù; không có gì đảm bảo rằng nó sẽ tiếp tục hoạt động theo cách đó, và tôi khá chắc chắn rằng trong các phiên bản cũ, nó * không * làm việc theo cách đó. –

+0

@Rob: bạn có thấy rằng trong VCL/RTL không? Coz quan tâm nếu tuyên bố của bạn dựa trên quan sát, nó có thể liên quan đến máy của bạn. Tôi nhớ một khi có một ứng dụng hoạt động tốt trên một máy và gặp sự cố với AV trên một máy khác, sự khác biệt duy nhất là bộ xử lý và/hoặc cách bộ nhớ được khởi tạo bởi hệ điều hành ... –

2

Trong thực tế Embarcadero sẽ luôn bằng zero khởi tố mới đơn giản chỉ vì để làm nếu không sẽ phá vỡ rất nhiều mã.

Trên thực tế, thật đáng tiếc là họ không chính thức đảm bảo phân bổ bằng 0 vì nó rất hữu ích. Vấn đề là thường tại trang gọi khi viết SetLength bạn không biết liệu bạn đang phát triển hay thu hẹp mảng. Nhưng việc thực hiện SetLength không biết - rõ ràng nó phải. Vì vậy, nó thực sự có ý nghĩa để có một hành động được xác định rõ trên bất kỳ yếu tố mới nào. Hơn nữa, nếu họ muốn mọi người có thể dễ dàng chuyển đổi giữa các thế giới được quản lý và bản địa thì không cần phân bổ vì đó là điều phù hợp với mã được quản lý.

+0

* 'Trong thực tế Embarcadero sẽ luôn luôn không khởi tạo' * - Bạn có biết tình cờ nếu điều này cũng đúng với Pascal miễn phí không? – Wolf

+1

Tôi không, vì tôi không sử dụng Free Pascal. Nhưng phải dễ dàng kiểm tra mã nguồn của họ. Hơn nữa, tôi sẽ ngạc nhiên nếu họ không làm tương tự như Delphi vì chúng được thúc đẩy để làm cho nó dễ dàng để viết mã hoạt động như nhau trong cả Delphi và FPC. –

+0

Cảm ơn gợi ý. Những gì tôi đã tìm thấy trong 'C: \ lazarus \ fpc \ 2.6.4 \ source \ rtl \ inc \ dynarr.inc' (bắt đầu từ dòng 137) trông như thế này. BTW: Nó không dễ tìm, tôi phải tạo ra một lỗi trình gỡ rối ('SetLength (myArray, -1);') để có được 'SetLength' được dịch thành' fpc_dynarray_setlength' ;-) – Wolf

Các vấn đề liên quan