Fortran 数组中的变量被删除?

Variables being deleted in Fortran Arrays?

我有以下代码,其中包含一个抽象类型、继承类型和一个简短的程序,我在其中创建一个对象并将其存储在一个数组中。

module m
    implicit none

    type :: container
        class(a), allocatable :: item
    end type container

    type, abstract :: a
        integer, public :: num
    end type a

    type, extends(a) :: b
        integer, public :: num2
   end type b
end module m

program mwe
    use m

    implicit none

    class(a), allocatable :: o1
    class(container), allocatable :: arr(:)

    o1 = b(1, 2)

    allocate(arr(2))
    arr(1) = container(o1)

    select type(t => o1)
        type is(b)
        write(*,*) t%num, t%num2
    end select

    select type(t => arr(1)%item)
        type is(b)
        write(*,*) t%num, t%num2
    end select
end program mwe

问题是,输出如下所示:

       1           2
       1           0

可以看出,存储在数组中的同一个变量第二个变量无效。为什么会这样?是不是因为数组是a类型,只包含第一个变量?

我正在用 ifort version 18.0.3 编译代码。

与 ripero 的 一样,可以说程序的任何输出都是有效的。但是,我们可以对代码进行简单的修改,使其正确的Fortran。1这个答案是关于这个修改版本的。

我会称之为意外输出并寻求编译器供应商的帮助。

使用具有多态可分配组件的结构构造函数是 Fortran 中的新领域之一。编译器可能需要一段时间才能赶上或正确完成。

我已经使用 Intel Fortran 18.0.2 测试了您的代码并看到了相同的输出。

针对您的问题

Is it because the array is of type a, which only contains the first variable?

否:在 select type 部分,输出 t 是类型 b.

的非多态实体

您可以通过避免使用结构构造函数来解决此问题:

arr(1)%item = o1

我还看到 18.0.2 之前的英特尔编译器做了一些不同的事情。


1 随声明

    class(container), allocatable :: arr(:)

arr 是多态的和可分配的。正如 ripero 所指出的,这意味着 arr(1)arr 的元素是多态的。但是,作为数组元素,arr(1) 本身不是多态的,因此可能不会位于内部赋值语句的左侧。我们可以通过两种方式更改代码:提供定义的赋值,或者使 arr 不是多态的。在问题的代码中似乎没有理由让容器多态,所以我会考虑

type(container), allocatable :: arr(:)

此外,正如问题评论中所讨论的,如果您希望使用 gfortran 8 或更早版本,看看会发生什么,您还应该修改问题中的代码,以便派生类型的定义 container 出现在派生类型 a.

的定义之后

我相信

arr(1) = container(o1)

在 Fortran 2008 中是无效的。这是一个内部赋值语句,但是标准的第 7.2.1.2 节说

In an intrinsic assignment statement, (1) if the variable is polymorphic it shall be allocatable and not a coarray.

据我所知,arr(1) 是多态的但不可分配,因此符合标准的编译器应该发出错误并中止编译。

如果我的推理是正确的,英特尔 Fortran 编译器编译此代码的事实是一个编译器错误,应该报告给英特尔。