通过赋值与显式分配/释放的隐式分配

问题描述 投票:1回答:2

如果我的编译器符合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

fortran
2个回答
4
投票

我将列出差异,优势或劣势是主观的。

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

对于那些不习惯动态语言的人来说,大多数作业都会进行一些分配,这可能是一个重要的事实,在deallocatereallocate语句中明确可见,重新分配实际上正在发生。

通过自动重新分配,编译器可能会使用realloc,尤其是在像a = [a, 1]这样的情况下。但据我所知,编译器目前不这样做。然而,通常的malloc将经常重新使用旧阵列所在的内存,如果它适合那里。


3
投票

优点是代码简洁。

integer, allocatable :: i(:)

i = [1, 2, 3]

少了一行

integer, allocatable :: i(:)

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

此外,您不需要明确写出分配的大小,因此冗余信息会少一些。

不方便的是它是一个自动功能。

我可以很容易地想到两个特征是缺点的场景。

  1. 数组i在分配时被重新分配,原因很充分(即代码中没有错误)并引入了可能更难找到的性能损失。
  2. 由于代码中存在逻辑错误,因此重新分配了数组i。这个bug会更容易被发现,因为随之而来的越界内存访问会引发一个段错误:-)

您可能会使用编译器检查检测到“2”,并使用分析器解析“1”。所以,除非你有充分的理由不使用这个功能,否则我会说“使用它”。但是,对于现有的代码库,没有特定的动机去除“仅仅因为”的分配语句。

© www.soinside.com 2019 - 2024. All rights reserved.