3

根据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_mytypeprint_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
  • 第 1 行:好的,t1 初始化为默认值 0
  • 第 2 行:好的,t2 初始化为默认值 0
  • 第 3 行:好的,分配新对象后t1%mytype(1),旧版本被删除
  • 第 4 行:好的,nr = 1打印版本
  • 第5行:奇怪,一个版本nr=-2来自哪里?
  • 第 6 行:好的,版本nr = 2已初始化
  • 第 7 行:好的,分配新对象后t2 = init_mytype(2),旧版本被删除
  • 第 8 行:奇怪,t2 是在调用之前完成的t2%print_mytype()
  • 第9行:奇怪,t2在finalization之后打印

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

4

1 回答 1

4

看起来奇怪的其实是定稿规则的结果。在 Fortran 2008 4.5.6.3(“当完成时”)中,给出了完成的提示。

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

第 1 行:好的,t1 初始化为默认值 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()在语句中的两个 finalization 调用之后发生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

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

  • 当执行内部赋值语句时,变量在 expr 评估之后和变量定义之前完成。
  • 如果一个可执行结构引用了一个函数,则在执行包含该引用的最里面的可执行结构后,将最终确定结果。

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

考虑解释请求“构造值最终确定了多少次?” 更正。构造函数的结果被认为没有最终确定,纠正了 Fortran 2003 中的一个错误。这可能是相关的,因为您确实询问了 Fortran 2003(尽管 ifort 明确实施了新规则)。

于 2015-03-13T11:58:53.203 回答