假设我们有这个变量定义
Real*8, Dimension(:), Allocatable :: dblA
Allocate (dblA(1000))
Run Code Online (Sandbox Code Playgroud)
现在我调用这个子程序:
Call MySub(dblA)
Run Code Online (Sandbox Code Playgroud)
其中:
Subroutine MySub(dblA)
Real*8, INTENT(Out), DIMENSION(1000) :: dblA
End
Run Code Online (Sandbox Code Playgroud)
这种做法有什么副作用?我应该避免这个吗?
如果在传递给子例程之前已经分配了数组,则子例程与allocatable-ness无关,效果与数组是静态的相同.在你向我们展示的片段中,没有什么可以反对,也没有练习避免.但是,这些片段实际上做得很少,很容易想到扩展它们以使这个建议无效的方法.
现在帮自己一个忙,改变吧
Real*8, INTENT(Out), DIMENSION(1000) :: dblA
Run Code Online (Sandbox Code Playgroud)
至
Real*8, INTENT(Out), DIMENSION(:) :: dblA
Run Code Online (Sandbox Code Playgroud)
这样无论传递的数组大小如何,子程序都能正常工作.使用dblA虚拟和实际参数的名称可能也是一个坏主意,你只会迷惑自己.
并且real*8,并且从来没有,是一种标准兼容的声明8字节实数的方式.关于这一点,请参阅SO上的众多问题和答案.
高性能马克的回答说明了我想要的一切。不过,为了强调,我将重复一个方面。
非常需要在调用子程序时分配子程序中的可分配数组。[就问题而言,大小足够。]
为了使这个答案不仅仅是一个评论,我将解决更一般的问题标题。在此之前,我将看看围绕“可分配或不可分配虚拟参数”的思考中可能出现的内容。
因为虚拟参数(子例程中的参数)具有intent(out)it 属性,而实际参数则变为未定义。如果虚拟参数是可分配的,那么它也会在进入时被释放。在这种情况下,实际参数保持分配状态并保持其原始大小。
如果虚拟参数(和实际参数)不可分配,则无法查询或更改分配状态;即使实际参数可以,虚拟参数也不能进一步传递给需要可分配参数的过程。
如果虚拟参数是可分配的而不是(静态)显式形状数组,则实际参数也必须是可分配数组。
使用可分配的虚拟参数,在引用子例程时将需要显式接口。[有些人会说,即使在隐式接口很好的情况下,这也是一个好主意。]
谈到更一般的事情,我将举一个例子,其中对可分配的实际/不可分配的虚拟对象有限制(F2008,12.5.2.4):
如果实际参数是多态共索引对象,则虚拟参数不应是多态的。
但对于大多数人来说,这并不是什么值得担心的事情。
哦,还有一件事我会从另一个答案中强调:Real*8应该避免。