2016-12-04 65 views
4

說我傳遞的陣列的片分爲操縱其輸入的子程序:在Fortran中,切片數組是否在內存中創建副本?

some_subroutine(a(:,1)) 

是對原始a改變的那部分,或的a(:,1)一些拷貝改變?

+0

對於gfortran,選項「-Warray-temporaries」或「-fcheck-array-temporaries」可用於獲取有關臨時對象的一些信息。另外,你可以打印實際數組和虛擬數組的第一個元素的地址,以檢查它們是否指向相同的內存(例如,使用c_loc()或loc())。 – roygvib

回答

5

有幾個其他的答案,這或許略微解決不同(但相關)的要點。在這裏我會試着調和它們。

Vladimir F's answer着眼於所謂的拷入/拷出機制; bfletch's answer對論點的最終影響。

一般而言,以下

integer i(2,2) 
i=0 
call dosomething(i(1,:)) ! Just to make it not contiguous. 

contains 
    subroutine dosomething(j) 
    integer j(2) ! or j(*), or j(:) 
    j=1 
    end subroutine 
end program 

的效果是,該陣列具有i設置爲1一些元件和其他0。所以,是的:無論是否存在臨時副本(來自一個答案),在調用之後可以觀察到的是,它是修改後的實際參數本身。

當然,還有一個例外:value屬性。 如果上述子程序,而不是像

subroutine doseomthing(j) 
    integer, value :: j(2) 
    j=1 
end subroutine 

那麼確實是有爭論的真實副本。對虛擬參數j的修改不會反映在i部分的實際參數中。


這是當前的Fortran。 Fortran 90作爲標記,沒有此功能。

+0

現在看來,你可能更好地閱讀OP的實際意圖。問題在於標題是「它是否在內存中創建副本」,但最後的問題是原始內容是否被修改。 –

+0

我只是剛剛注意到這是一個自我回答的問題,但即使在這種情況下,說臨時副本也是非常有價值的。可能我還可以補充一點:關於創建副本的切片沒有任何意義,在這裏我們只關注切片作爲參數的情況。陣列片分配也可能需要臨時副本。 – francescalus

4

這取決於如果a本身是連續的,並且some_subroutine看起來如何。

你大概默默地認爲a是連續的,但它不一定是,如果a本身是一些作爲假設形狀數組或數組指針傳遞的切片。

即使a是不連續的,並因此也a(:,1)沒有,將不會如果some_subroutine接受一個假定外形的參數需要一個拷貝

subroutine some_sub(b) 
    real :: some_sub(:) 
相關問題