作为Steve Lionel的
答案,以及我原始回答中的评论,这些或许激发了你的兴趣,
intent(out)
对于虚拟参数(以及实际参数)初始状态的影响是回答这个问题的一种方式。
intent(inout)
使虚拟参数反映进入过程时实际参数的值。
intent(out)
“重置”虚拟参数。在链接的问题中,这种“未定义”是程序无效的原因。
更准确地说,我们可以关于
intent(out)
虚拟参数说以下事情:
- 可分配实际参数将被取消分配;
- 指针实际参数的指针关联变得未定义;
- 对于非指针虚拟参数,任何未默认初始化的组件都变得未定义。
链接的问题因尝试引用这样一个新定义的值而违反了第三点。然而,默认初始化的组件不是未定义的,这导致我们获得了第一类有效程序:
implicit none
type t
integer :: x=1
end type t
type(t) :: x=t(0)
call s1(x)
call s2(x)
contains
subroutine s1(x)
type(t), intent(inout) :: x
print*, x%x
end subroutine s1
subroutine s2(x)
type(t), intent(out) :: x
print*, x%x
end subroutine s2
end
重要的是,组件的默认初始化意味着即使在进入s2时,x%x也不是未定义的,但它可能与过程输入之前的实际参数组件的值不同。
使用指针参数编写合适的程序很棘手:具有未定义指针关联状态的指针无法在重新定义其指针关联状态之前被引用/查询。
这让我们看到了可分配组件。与指针不同,在该指针关联状态未定义时,我们无法查询指针关联状态,但我们可以询问分配状态。与intent(out)虚参对应的实参已被解除分配;对于intent(inout),分配状态保持不变:
implicit none
integer, allocatable :: i
allocate (i)
call s1(i); print*, allocated(i)
call s2(i); print*, allocated(i)
contains
subroutine s1(i)
integer, allocatable, intent(inout) :: i
end subroutine s1
subroutine s2(i)
integer, allocatable, intent(out) :: i
end subroutine s2
end
(这是 Steve Lionel 示例的简化版本。)
所有这些都表明存在差异。不正确使用 intent
可能导致无效程序或意义上的重大变化。理解 intent(in)
、intent(inout)
、intent(out)
和未指定 intent 意味着成为 Fortran 程序员的关键部分。
ALLOCATABLE
- 变量可以是任何类型。按照标准,INTENT(OUT)
意味着虚拟参数的定义状态在进入过程时是“未定义”的,但在其他情况下很难检测。关于@francescalus使用“disassociates”这点,让我感到不安。指针会被取消关联,而INTENT(OUT)
会导致指针未定义,而不是解除关联,因此您不能假设或甚至测试指针是否已解除关联。 - Steve Lionel