Xia*_*Zhu 3 fortran operator-overloading assignment-operator
我正在尝试使用 fortran 2003 实现一个多项式类,其中包含重载的算术运算和赋值。派生类型维护术语定义和系数的可分配列表,如下所示
type polynomial
private
type(monomial),dimension(:),allocatable :: term
double precision,dimension(:),allocatable :: coef
integer :: nterms=0
contains
...
end type polynomial
interface assignment(=)
module procedure :: polynomial_assignment
end interface
...
contains
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(???) :: lhs
type(polynomial),intent(in) :: rhs
...
Run Code Online (Sandbox Code Playgroud)
我必须使它成为基本的,因为它旨在用作多项式矩阵。这确实有效,至少在大多数情况下是这样。然而,我不知何故让自己担心这里的自我分配。可以简单地检查指针以查看 C++ 中的内容是否相同,但它似乎不是 Fortran 中的一个选项。但是编译器确实检测到自赋值并给了我一个警告。(gfortran 4.9.0)
当我有lhs 的意图(输出)时, lhs 和 rhs 的可分配条目似乎在进入子例程时被释放,这是有道理的,因为它们都是 p,并且意图(输出)参数将首先被最终确定。
然后我尝试通过意图(inout)避免解除分配,并通过修改 lhs 输出中的一个字段来检查自分配
elemental subroutine polyn_assignment(lhs,rhs)
implicit none
type(polynomial),intent(inout) :: lhs
type(polynomial),intent(in) :: rhs
lhs%nterms=rhs%nterms-5
if(lhs%nterms==rhs%nterms)then
lhs%nterms=rhs%nterms+5
return
end if
lhs%nterms=rhs%nterms
Run Code Online (Sandbox Code Playgroud)
好吧,现在这让我感到惊讶。当我做
p=p
Run Code Online (Sandbox Code Playgroud)
它没有进行测试并继续进行,给了我一个具有 0 项但没有内存违规的多项式。一头雾水,我在赋值里面打印了lhs%nterms和rhs%nterms,才发现它们不一样!
更令人困惑的是,当我用
call polyn_assignment(p,p)
Run Code Online (Sandbox Code Playgroud)
它完美运行并检测到两个参数相同。我很困惑子程序的接口如何与子程序本身不同地运行。
我错过了 Fortran 2003 中的赋值有什么特别之处吗?
(第一次在这里提问。如果我做的不对,请纠正我。)
如果您有一条语句a = b通过子例程调用定义的赋值sub,则赋值语句等效于call sub(a, (b)). 请注意括号 - 右侧的参数是对带括号的表达式求值的结果,因此在概念上与b. 详见 F2008 12.4.3.4.3。
因此,a = a等价于call sub(a, (a))。这两个参数没有别名。它不同于call sub(a,a),后者可能(取决于 的内部细节sub,包括虚拟参数属性)破坏 Fortran 的参数别名规则(例如,在您的示例中,诸如call polyn_subroutine(a,a)是非法的语句)。