在 Fortran 重载赋值中检查自赋值

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 中的赋值有什么特别之处吗?

(第一次在这里提问。如果我做的不对,请纠正我。)

Ian*_*anH 5

如果您有一条语句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)是非法的语句)。