分配隐式分配与显式分配/取消分配

时间:2019-02-04 22:17:21

标签: fortran

如果我的编译器符合 Fortran 2003 ,我可以按Automatic array allocation upon assignment in Fortran中的说明进行重新分配,而无需进行明确的取消分配/分配过程。例如

integer, allocatable :: i(:)

i = [1,2,3]
i = [1,2,3,4,5]

相对于旧的( Fortran 90 )方式:

if( allocated(i) ) deallocate(i)
allocate(i(3))
i = [1,2,3]
if( allocated(i) ) deallocate(i)
allocate(i(5))
i = [1,2,3,4,5]

此新技术的缺点或缺点是什么?当然,这比旧方法要简洁得多。但是,是否有理由偏爱旧方法?我仍然在代码示例中看到的是旧方法,而不是新方法,但这也许仅仅是因为Fortran 90的使用率仍高于Fortran 2003。

作为快速的计时检查,我在gfortran 4.8.5下将上述代码循环了100,000,000次,发现新方法似乎也更快,运行时间约为4秒(新方法)与6秒(旧方法)。相反,在以下注释中,@ roygvib在gfortran 8.2中得到的结果基本上相反。

另外,请注意以下有关该问题的最新讨论:Fortran Discussion Group

2 个答案:

答案 0 :(得分:4)

我将列出这些差异,优点或缺点是主观的。

编译器必须检查每个整个数组分配的正确界限-但这必须发生,即使您不使用重新分配。除非您在某些编译器中完全禁用此标准功能。

对于那些不习惯使用动态语言的大多数分配进行某种分配的语言,这可能是一个重要事实,即在deallocatereallocate语句中,可以明显看出实际上正在发生重新分配。 / p>

通过自动重新分配,编译器可以潜在地使用realloc,尤其是在a = [a, 1]之类的情况下。但据我所知,编译器目前不这样做。不过,通常的malloc经常会在旧数组适合的地方重用内存。

答案 1 :(得分:3)

好处是代码简洁。

integer, allocatable :: i(:)

i = [1, 2, 3]

比第一行少

integer, allocatable :: i(:)

allocate(i(3))
i = [1, 2, 3]

此外,您无需显式编写分配的大小,因此冗余信息要少一些。

不方便之处在于它是自动功能。

我很容易想到该功能不利的两种情况。

  1. 出于充分的理由(即代码中的错误),数组i在分配时被重新分配,并且引入了性能上的损失,这可能很难找到。
  2. 由于代码中的逻辑错误,数组i被重新分配。如果随后发生的越界内存访问引发了段错误,则更容易检测到该错误:-)

您可能会通过编译器检查检测到“ 2”,并使用探查器解决“ 1”。因此,除非您有好的理由不使用该功能,否则我会说“使用它”。但是,对于现有的代码库,没有“只是因为”而删除分配语句的特定动机。