2012-08-03 33 views
7

Tôi cần một bản sao sâu của một mảng (thực) trong Fortran (90), nhưng không chắc chắn chính xác làm thế nào để có được một, vì tôi không hoàn toàn hiểu cách tham chiếu hoạt động. Bằng trực giác, tôi sẽ mong đợi điều này để làm cho tôi những gì tôi muốn:Sao chép mảng sâu trong Fortran

do i=1,n 
    b(i) = a(i) 
end do 

Tuy nhiên, nó đã được thời gian gần đây chỉ ra cho tôi rằng b(1:n) = a(1:n) là tương đương với các mã trên. Theo trực giác, tôi mong đợi rằng b(1:n) = a(1:n) chỉ đơn thuần là nguyên nhân tham chiếu của b(1:n) để trỏ đến vị trí của a(1:n) trong bộ nhớ.

Có phải là b(1:n) = a(1:n) bản sao sâu? Tại sao? Điều gì đang xảy ra với các tham chiếu cơ bản như trái ngược với b = a?

Trả lời

13

Ba cách bạn đề cập đến cho mảng sao chép, các do vòng lặp, b(1:n) = a(1:n)b = a, tất cả đều tương đương; họ sao chép nội dung của mảng a vào mảng b. ab chỉ đơn giản là mảng, không phải là con trỏ ưa thích hoặc bất kỳ thứ gì và do đó việc gán a = b về cơ bản giống như biểu thức toán học. Không có phép thuật với các tham chiếu đang diễn ra (mà người dùng cần biết), đó là lý do tại sao Fortran là một ngôn ngữ khá thẳng về phía trước để học. Bạn có thể có các mảng con trỏ trong Fortran, nhưng đây là một vấn đề khác.

M Metcalf và J Reid Fortran 90/95 giải thích luôn là tài liệu tham khảo tốt cho tư vấn về các tính năng ngôn ngữ của Fortran. Từ trang 48:

3,11 Mảng phân

Bằng cách phân nội tại, một biểu thức mảng có thể được gán cho một biến mảng của hình dạng tương tự, được hiểu là nếu mỗi phần tử của biểu thức được chỉ định thành phần tử tương ứng của biến. Ví dụ, với các tờ khai

real, dimension(10, 20) :: a 

Việc chuyển nhượng

a = a + 1.0 

thay thế a(i,j) bởi a(i,j) + 1.0 cho i=1,2..,10j=1,2,..,20.

Cũng lưu ý rằng một biểu thức vô hướng có thể được gán cho một mảng, trong trường hợp giá trị saclar được phát sóng đến tất cả các phần tử mảng.

Xét về cách thực hiện điều này thực sự được thực hiện, đó là những gì tôi nghĩ bạn đang lái xe cùng với câu hỏi của bạn, điều này hoàn toàn không được chỉ định theo tiêu chuẩn Fortran. Loại điều này là trái không xác định để cho phép các nhà văn biên dịch làm bất cứ điều gì tối ưu họ cảm thấy như thế nào. Ví dụ, trong nhiệm vụ a = b, thứ tự các thành phần của b được sao chép vào a không được chỉ định theo tiêu chuẩn, do đó các trình biên dịch khác nhau có thể thực hiện điều này theo nhiều cách khác nhau. Tất cả những gì bạn cần biết là, với điều kiện là ab không phải là con trỏ, thì ab là các mảng riêng biệt và thay đổi thành phần của một yếu tố không thay đổi phần tử tương ứng. Vì vậy, nó là một cảm giác, a=b là một "bản sao sâu" và bạn có thể nghĩ về điều này như sao chép tất cả các mục trong b đến vị trí bộ nhớ của a.

+0

@ IanH Đây không phải là điều tôi biết nhiều, vì vậy tôi chỉ tập trung vào mảng trong câu trả lời của mình. Nó sẽ là thú vị để xem một ví dụ về ở trên không phải là trường hợp cho các loại có nguồn gốc nếu bạn muốn gửi một câu trả lời. – Chris

+0

Lời xin lỗi cho điều đó, đó là một bong bóng suy nghĩ chưa hoàn thành mà tôi đã quyết định là không liên quan đến câu hỏi (với áp phích cụ thể đề cập đến các biến REAL). Tôi thậm chí không biết rằng nó đã được đăng. – IanH

+1

'b (1: n) = a (1: n)' và 'b = a' không tương đương. Ví dụ, trước đây sẽ không kiểm tra sự phân bổ lại cần thiết. –

6

a = b sao chép toàn bộ mảng b vào a. Nếu bạn chỉ muốn một phần của mảng được kích thước lớn hơn n, thì bạn có thể sử dụng ký hiệu chỉ số a (1: n) = b (1: n). Đó là Fortran 90 - nó là một ngôn ngữ bậc cao hơn FORTRAN 77. Chúng ta có thể nói rằng "a = b" là một bản sao và không liên kết con trỏ với mục tiêu b bởi vì câu lệnh đó sử dụng toán tử "=". Liên kết con trỏ sử dụng =>.

Chỉnh sửa: theo bản sao, nó tạo bản sao, có thể cùng một mã máy như vòng lặp do của bạn. Hiệp hội con trỏ tạo một tham chiếu mà không thực hiện vòng lặp do để sao chép tất cả các phần tử mảng.

Xem http://en.wikipedia.org/wiki/Fortran_95_language_features

+1

Sao chép nó? Bằng cách bổ sung tham chiếu 'a' vào vị trí của' b' trong bộ nhớ, hoặc bằng cách di chuyển một bản sao của tất cả các mục trong 'b' đến vị trí của' a' trong bộ nhớ? – astay13

+2

@ astay13, Fortran không phải là Java hoặc C#. Nó không có tài liệu tham khảo. Nó có con trỏ nhưng những cú pháp sử dụng đặc biệt để liên kết như M. S. B. đã chỉ ra ('=>' thay vì '='). Ví dụ 'gfortran' thực hiện sao chép mảng bằng cách sử dụng hoặc 'memcpy' (bản sao bộ nhớ bitwise, rất nhanh) hoặc các vòng lặp' DO' ẩn, tùy thuộc vào ngữ cảnh. –

+0

@HristoIliev, vâng, câu hỏi đặt ra là vì Java là ngôn ngữ đầu tiên của tôi nên tôi đã từng nghĩ về '=' được sử dụng để gán tham chiếu. – astay13