如果我的编译器符合 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
答案 0 :(得分:4)
我将列出这些差异,优点或缺点是主观的。
编译器必须检查每个整个数组分配的正确界限-但这必须发生,即使您不使用重新分配。除非您在某些编译器中完全禁用此标准功能。
对于那些不习惯使用动态语言的大多数分配进行某种分配的语言,这可能是一个重要事实,即在deallocate
和reallocate
语句中,可以明显看出实际上正在发生重新分配。 / 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]
此外,您无需显式编写分配的大小,因此冗余信息要少一些。
不方便之处在于它是自动功能。
我很容易想到该功能不利的两种情况。
i
在分配时被重新分配,并且引入了性能上的损失,这可能很难找到。i
被重新分配。如果随后发生的越界内存访问引发了段错误,则更容易检测到该错误:-)您可能会通过编译器检查检测到“ 2”,并使用探查器解决“ 1”。因此,除非您有好的理由不使用该功能,否则我会说“使用它”。但是,对于现有的代码库,没有“只是因为”而删除分配语句的特定动机。