6

私は 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 つを割り当てたままにしていると思われます。

はるかに複雑なコードでこのようなルーチンを何度も使用するつもりなので、メモリの割り当て/割り当て解除について本当に心配しています。もちろんサブルーチン版のプログラムでもいいのですが、方法があれば関数版の方がいいと思います。

このような問題に対処する方法はありますか?

4

2 に答える 2

1

これは、関数とサブルーチンについて私がしばらく前に受けた質問に似ています。

fortran 演算子のオーバーロード: 関数またはサブルーチン

割り当てと解放が可能なサブルーチンを使用することと、割り当てしかできない関数を使用することの間には、ある種のトレードオフがあると思います。データ構造が大きい場合は、関数をこの用途に使用することを避け、サブルーチンに固執することをお勧めします。

于 2016-04-08T16:48:22.803 に答える