如果我的编译器符合Fortran 2003标准,我可以在没有显式deallocate / allocate过程的情况下重新分配可分配的变量或数组,如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
我将列出差异,优势或劣势是主观的。
编译器必须检查每个整个数组赋值的正确边界 - 但即使您不使用重新分配,也必须发生这种情况。除非您在某些编译器中完全禁用此标准功能。
对于那些不习惯动态语言的人来说,大多数作业都会进行一些分配,这可能是一个重要的事实,在deallocate
和reallocate
语句中明确可见,重新分配实际上正在发生。
通过自动重新分配,编译器可能会使用realloc
,尤其是在像a = [a, 1]
这样的情况下。但据我所知,编译器目前不这样做。然而,通常的malloc
将经常重新使用旧阵列所在的内存,如果它适合那里。
优点是代码简洁。
integer, allocatable :: i(:)
i = [1, 2, 3]
少了一行
integer, allocatable :: i(:)
allocate(i(3))
i = [1, 2, 3]
此外,您不需要明确写出分配的大小,因此冗余信息会少一些。
不方便的是它是一个自动功能。
我可以很容易地想到两个特征是缺点的场景。
i
在分配时被重新分配,原因很充分(即代码中没有错误)并引入了可能更难找到的性能损失。i
。这个bug会更容易被发现,因为随之而来的越界内存访问会引发一个段错误:-)您可能会使用编译器检查检测到“2”,并使用分析器解析“1”。所以,除非你有充分的理由不使用这个功能,否则我会说“使用它”。但是,对于现有的代码库,没有特定的动机去除“仅仅因为”的分配语句。