函数返回值过早完成

bdf*_*bes 1 fortran intel-fortran

我有一个t_file带有终结例程的派生类型,close它只是将" 终结"写入屏幕.还有一个函数返回该类型的实例t_file.这个程序的输出是

Finalization.
Finalization.
Just opened
     2000
Done.
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  • 为什么定稿发生之前Just opened输出?
  • 为什么定稿会发生两次

我的编译器是英特尔(R)Visual Fortran Composer XE 2011 12.1.3526.2010.

这是代码:

module m_file
    implicit none


    type t_file
        integer::iu=1000

        contains

        final::close
    end type

    contains

    function openFile() result(f)
        implicit none

        type(t_file)::f

        f%iu = 2000

    end function

    subroutine close(this)
        implicit none

        type(t_file)::this

        write(*,*) 'Finalization.'

    end subroutine

end module

program foo
    use m_file
    implicit none

    type(t_file)::f

    f = openFile()
    write(*,*) 'Just opened'
    write(*,*) f%iu

    write(*,*) 'Done.'    
    read(*,*)

end program
Run Code Online (Sandbox Code Playgroud)

Hig*_*ark 5

这种行为也让我感到惊讶.我一直在掌握Fortran的新(-ish)OO功能,但还不需要编写最终的程序.我认为我可以为这种行为提供各种解释.

现代Fortran的 p282 解释作者写道:

当一个可终结的对象即将停止存在时(例如,通过解除分配或执行一个return语句),最终的子程序将以对象作为其实际参数进行调用.当对象传递给intent out伪参数时,或者在内部赋值语句的左侧是变量时,也会发生这种情况.在后一种情况下,在评估右侧的表达式之后,但在将其分配给变量之前,将调用最终子例程.

它看起来好像你正在触及本段中提到的两种情况.Finalizationf函数内部命名的实体openFile在从该函数返回时将超出范围时,您将获得第一个.

Finalizationf程序范围中的变量用于赋值的lhs时,您得到第二个f = openFile().

从这一切我得出结论,你没有看到f在程序范围内过早完成,但有些微妙的不同.

我并不完全相信这就是正在发生的事情,我无法想到为什么语言的行为应该如此.我有点惊讶,现在我已经调查过了,Finalization当程序结束并f超出范围时,你没有收到第三条消息.

运气好的话,真正的Fortran大师很快就会过去并启发我们所有人.