在下面的代码中,我试图通过首先分配更大的临时数组a(:)
来增加buf(:)
的长度,将a(:)
的内容复制到buf(:)
},然后使用move_alloc()
将数组描述符从buf
复制到a
:
program main
implicit none
integer, allocatable :: a(:), buf(:)
allocate( a(2) )
a = [1,2]
allocate( buf( 4 ), source= 0 ) !! (1)
buf( 1:2 ) = a( 1:2 ) !! (2)
! allocate( buf( 4 ), source= a ) !! (3)
! deallocate( a ) !! (4)
call move_alloc( buf, a )
print *, "a(:) = ", a(:)
end
在这里,我有两个问题:首先,在第4行中,是否有必要在调用a(:)
之前明确解除move_alloc()
...?即使没有第4行,gfortran和英特尔Fortran似乎都能正常工作,但这是否意味着move_alloc()
如果预先分配了a(:)
会自动解除分配?{1}}?其次,我们可以将第1行和第2行替换为3,即使用具有不同长度数组的源分配吗?我已经对此进行了实验,而且,gfortran和英特尔Fortran似乎都接受了(显然)正确的结果。
答案 0 :(得分:3)
根据Fortran标准(2008年,13.7.118)关于move_alloc
,我们有参数to
的细节(子例程的第二个参数)
这是一个INTENT(OUT)参数
与您在gfortran manual的链接中提供的说明相匹配。
对于具有intent(out)
和allocatable
属性的任何其他伪参数,与to
关联的实际参数将在调用子例程move_alloc
时被释放。也就是说,您不需要自己解除a
。
关于源分配,我们already know分配的数组必须与源数组一致,以便编写
allocate(buf(4), source=a) ! a is the same rank as buf, but extent 2
无效,与
一样多allocate(buf(4), source=a(1:2))
是
然而,虽然对于源分配存在一些编号限制,但这种一致性要求并未在其中一个中具有特征。因此,您的编译器不需要检测您的代码是否不符合。
当然,编译器允许进行投诉,正如您在使用a(1:2)
作为源时所看到的那样。在某种程度上,在编译时更容易看到范围4的数组与a(1:2)
不符合a
的情况。您可以尝试使用a(1:SIZE(a))
进行试验,以了解编译器在此类测试中花费了多少精力。
作为最终评论,当然可以使用单一来源分配来替换第1行和第2行:
allocate(buf, source=[a,0,0]) ! Buf is 2 longer than a
但这并不一定“更好”。
答案 1 :(得分:2)
编写Fortran标准,以便您不必了解可分配内存泄漏。如果首先不禁止操作,则不应导致任何泄漏。此规则适用于任何可能的标准符合操作和可分配变量。
因此,正如英特尔手册所述,to
参数将首先被解除分配。
答案 2 :(得分:1)
是否有必要解除分配
a(:)
:
更新我误读了您的问题。您在询问TO
部分。
我刚用valgrind
尝试过,似乎deallocate
似乎没有必要防止泄漏。但我可能仍然会这样做,只是为了安全起见。
第二个问题:
[我们可以] ......使用不同长度数组的源分配吗?
根据我信任的Fortran Book,没有:
[...] ...分配的数组必须与源数组或表达式一致(具有相同的等级和形状)。
然而,我的书还没有涵盖2003年以后的标准,因此Fortran 2008或Fortran 2015的情况可能会有所不同。