在 FORTRAN 2003 中完成

Finalisation in FORTRAN 2003

根据 Fortran Wikiintel fortran 编译器版本 14 应支持 FORTRAN 2003 标准中定义的最终化。我尝试将此功能与 ifort 14 一起使用,但观察到奇怪的行为。以下示例应说明这一点:

module mtypes
    implicit none

    type mytype
        integer, private :: nr
        contains

            final :: delete_mytype
            procedure :: print_mytype
    end type

    contains


!>      \brief Constructs a new mytype
!!      \return The created mytype
!>
        function init_mytype(number)
            type(mytype) :: init_mytype
            integer, intent(in) :: number
!            allocate(init_mytype)
            init_mytype = mytype(number)
            print *, 'init mytype', number
        end function

!>      \brief De-constructs a mytype object
!>
        subroutine delete_mytype(this)
            type(mytype) :: this   !< The mytype object that will be finalized
            print *, 'Deleted mytype!', this%nr
        end subroutine delete_mytype

!>      \brief Print something from mytype object
!>
        subroutine print_mytype(this)
            class(mytype) :: this   !< The mytype object that will print something
            print *, 'Print something from mytype!', this%nr
        end subroutine print_mytype


end module mtypes

program main

    use mtypes
    type(mytype) :: t1, t2

    call t1%print_mytype()
    call t2%print_mytype()

    t1 = mytype(1)
    call t1%print_mytype()
    t2 = init_mytype(2)
    call t2%print_mytype()

end program main

在这个完整的示例中,type mytype 被定义为只有一个值 nr。这种类型可以使用简单的类型构造函数创建,例如mytype(1) 或初始化函数 init_mytype。还定义了一个子例程 print_mytype,它只是将 mytype%nr 打印到标准输出。最后,final 例程 delete_mytype 应该用于完成,尽管在这个例子中它只打印一些信息到标准输出。

此示例给出以下输出:

 Print something from mytype!           0
 Print something from mytype!           0
 Deleted mytype!           0
 Print something from mytype!           1
 Deleted mytype!          -2
 init mytype           2
 Deleted mytype!           0
 Deleted mytype!           2
 Print something from mytype!           2

这种奇怪的行为是由某些 ifort 错误引起的,还是由于错误应用了最终化 FORTRAN 2003 功能而我做错了什么?

看似奇怪的,其实是敲定规则的结果。在 Fortran 2008 4.5.6.3 ("When finalization occurs") 中给出了完成的提示。

在谈到这些之前,先说说初始化。你说

Line 1: Ok, t1 initialised with default value 0

派生类型组件 nr 没有默认初始化,t1 也没有显式初始化,所以您的说法不正确。实际上,此时 t1%nr 是未定义的。 0正好是结果。这很重要,我们稍后会看到。

您的代码,以及关于完成的评论:

t1 = mytype(1)          ! t1 finalized before assignment
call t1%print_mytype()
t2 = init_mytype(2)     ! t2 finalized before assignment, after function
                        ! init_mytype result finalized after assignment
call t2%print_mytype()
                        ! No finalization before END PROGRAM (4.5.6.4)

您第 8 行和第 9 行的意外行为并不奇怪。特别是,call t2%print_mytype() 发生在语句 t2=init_mytype(2).

中的两个终结调用之后

现在,第 5 行的终结从何而来?为什么 -2?还记得没有初始化吗? -2 是允许的结果,如果对没有赋值的实体发生终结。哪个实体最终确定?

查看函数 init_mytype 返回类型 mytype:

的结果
function init_mytype(number)
  type(mytype) :: init_mytype    ! No initialization of result
  integer, intent(in) :: number

  init_mytype = mytype(number)   ! Result finalized before assignment
  print *, 'init mytype', number
end function

综上所述,本程序出现如下提示:

  • When an intrinsic assignment statement is executed, the variable is finalized after evaluation of expr and before the definition of the variable.
  • If an executable construct references a function, the result is finalized after execution of the innermost executable construct containing the reference.

顺便说一句,如果您查看 Fortran 2008 标准草案(例如我在该答案的早期修订版中错误地复制了错误的提示时所做的),您可能会想:为什么结果不是结构构造函数完成了吗?这应该发生两次:一次直接在程序中发生,一次通过调用 init_mytype 间接发生。但是我们没有看到这样的效果。

考虑解释请求 "How many times are constructed values finalized?" and the corrigendum。构造函数结果被认为是未最终确定的,更正了 Fortran 2003 中的错误。这可能是相关的,因为您确实询问了 Fortran 2003(尽管 ifort 明确实施了新规则)。