2015-04-21 425 views
6

我在Fortran中是OOP的初學者,我試圖編寫一個程序來處理多態變量作爲參數。 儘管我的原始代碼要複雜得多(很多過程,幾個派生類型等),但我可以分離出一個簡單的問題示例,例如:我有一個複製多態變量並略微修改此副本的過程。Fortran多態性,函數和分配

我是能夠成功地編寫使用子程序我的測試程序:

MODULE my_module 

type :: my_type 
    real :: data 
endtype my_type 

type, extends(my_type) :: my_derived_type 
end type my_derived_type 

CONTAINS 

subroutine sub_copy(old,new) 
implicit none 
class(my_type), intent(in) :: old 
class(my_type), allocatable, intent(out) :: new 
allocate(new, source = old) 
new%data = new%data + 1 
end subroutine sub_copy 

END MODULE my_module 

PROGRAM my_prog 
use my_module 
implicit none 
type(my_derived_type) :: x 
class(my_type), allocatable :: y 

x%data = 1.0 
call sub_copy(x,y) 
print*,y%data 
deallocate(y) 

END PROGRAM my_prog 

這很好地執行關於雙方的預期結果和內存分配/釋放。

但是,我一直在努力嘗試使Fortran 函數能夠完成同樣的工作。

看來,以類似的方式定義的子程序功能(後見這裏),不能簡單地用作

y = fun_copy(x) 

和我gfortran編譯器(V5.0.0)抱怨:

Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported 

我已經在這裏和那裏看到,我的編譯器不支持這樣的賦值。等待這個,我試圖通過定義我自己的賦值運算符(=)來解決這個問題。下面的代碼工作:

MODULE my_module 

type :: my_type 
    real :: data 
endtype my_type 

type, extends(my_type) :: my_derived_type 
end type my_derived_type 

interface assignment(=) 
    module procedure myassign 
end interface 

CONTAINS 

function fun_copy(old) result(new) 
implicit none 
class(my_type), intent(in) :: old 
class(my_type), allocatable :: new 
allocate(new, source = old) 
new%data = new%data + 1 
end function fun_copy 

subroutine myassign(new,old) 
class(my_type), intent(in) :: old 
class(my_type), allocatable, intent(out) :: new 
allocate(new, source=old) 
end subroutine 

END MODULE my_module 

PROGRAM my_prog 
use my_module 
implicit none 
type(my_derived_type) :: x 
class(my_type), allocatable :: y 

x%data = 1.0 
y = fun_copy(x) 
print*,y%data 
deallocate(y) 

END PROGRAM my_prog 

它工作在事實上,x副本爲y創建的意義。但是,檢查此簡單測試程序的內存預算(我在OS X上使用儀器軟件)時,看起來有些內存在其結束之前未取消分配。 我懷疑副本函數和分配子例程都分配內存,並且我只釋放一個事件,留下一個分配。因爲我打算在一個更復雜的代碼中使用這樣一個例程很多次,所以我非常關心內存分配/釋放。 當然,我可以使用子程序版本的程序,但如果有辦法,我寧願功能版本。

有沒有辦法處理這樣的問題?

+0

在你的函數示例中,你的意思是'y = fun_copy(x)',我猜。作爲另一個解決方法'分配(y,source = fun_copy(x))',但這不是很有吸引力。不過,看看同樣的事情是否會持續下去會很有趣。 – francescalus

+0

@francescalus是的我的意思是'y = fun_copy(x)'。我編輯了原文,並糾正了這個問題。另外,我剛剛嘗試了您的解決方法,並且內存分配/釋放問題仍然存在。據我所知,沒有任何變化。 – Reno

+0

嗯,我還沒有(但?)知道答案,但我想我們可以排除定義的分配問題。 – francescalus

回答

0

這聽起來類似的問題,我有一個前陣子關於功能VS子程序:

fortran operator overloading: function or subroutine

我覺得這是一種權衡使用子程序,它允許分配和回收之間,並使用一個只能分配的函數。我會建議,如果數據結構很大,則避免使用此功能並堅持子程序。

1

你試過用指針嗎?

module my_module 

     implicit none 

     type :: my_type 
      real :: data 
     contains 
      procedure    :: sub_copy 
      procedure    :: fun_copy_ptr 
      procedure    :: fun_copy_alloc 
      procedure, pass (this) :: my_assign 
      generic    :: assignment(=) => my_assign 
     end type my_type 

     type, extends(my_type) :: my_derived_type 
     end type my_derived_type 

    contains 

     subroutine sub_copy(this, new) 
      class(my_type), intent (in)    :: this 
      class(my_type), allocatable, intent (out) :: new 

      allocate(new, source=this) 
      new%data = new%data + 1 

     end subroutine sub_copy 

     function fun_copy_alloc(this) result (new) 
      class(my_type), intent(in) :: this 
      class(my_type), allocatable :: new 

      allocate(new, source=this) 
      new%data = new%data + 1.0 

     end function fun_copy_alloc 

     function fun_copy_ptr(this) result (new) 
      class(my_type), intent(in) :: this 
      class(my_type), pointer :: new 

      allocate(new, source=this) 
      new%data = new%data + 1.0 

     end function fun_copy_ptr 

     subroutine my_assign(new, this) 
      class(my_type), intent(in)    :: this 
      class(my_type), allocatable, intent(out) :: new 

      allocate(new, source=this) 

     end subroutine 

    end module my_module 

    program my_prog 

     use my_module, only: & 
      my_type, & 
      my_derived_type 

     implicit none 
     type(my_derived_type)  :: x 
     class(my_type), allocatable :: y 
     class(my_type), pointer  :: y_ptr => null() 

     x%data = 1.0 

     ! Case 1 
     call x%sub_copy(y) 
     print *, y%data 
     deallocate(y) 

     ! Case 2 
     y_ptr => x%fun_copy_ptr() 
     print *, y_ptr%data 
     deallocate(y_ptr) 

     ! Case 3 
     allocate(y, source=x%fun_copy_alloc()) 
     print *, y%data 
     deallocate(y) 

    end program my_prog