私は Fortran を使用した OOP の初心者であり、多相変数を引数として処理するプロシージャを使用してプログラムを作成しようとしています。私の元のコードははるかに複雑ですが (多くのプロシージャ、いくつかの派生型など)、問題の単純な例を分離できます。たとえば、ポリモーフィック変数をコピーし、このコピーをわずかに変更するプロシージャがあります。
サブルーチンを使用して、テスト プログラムを正常に作成できました。
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 でInstrumentソフトウェアを使用しています) のメモリ バジェットを調べると、終了前に一部のメモリが割り当て解除されていないようです。コピー関数と代入サブルーチンの両方がメモリを割り当て、1 つのオカレンスのみを解放し、1 つを割り当てたままにしていると思われます。
はるかに複雑なコードでこのようなルーチンを何度も使用するつもりなので、メモリの割り当て/割り当て解除について本当に心配しています。もちろんサブルーチン版のプログラムでもいいのですが、方法があれば関数版の方がいいと思います。
このような問題に対処する方法はありますか?