Fortran中的深度数组复制

12

我需要在Fortran(90)中深度复制一个(真实)数组,但我不确定如何获得它,因为我并不完全理解引用的工作原理。直觉上,我希望这样做可以得到我想要的结果:

do i=1,n
  b(i) = a(i)
end do

最近有人指出对我说,b(1:n) = a(1:n)与上面的代码等效。 直觉上,我会认为b(1:n) = a(1:n)仅仅是将b(1:n)的引用指向内存中a(1:n)的位置。

b(1:n) = a(1:n)是深拷贝吗? 为什么? 在底层引用方面发生了什么,与b = a不同?

2个回答

16
你提到的三种复制数组的方法,使用do循环、b(1:n) = a(1:n)b = a ,它们都是等效的;它们将数组a的内容复制到数组b中。 ab只是普通的数组,而不是什么高级指针之类的东西,所以赋值a = b基本上与数学表达式相同。这里没有任何引用的魔法(用户需要知道的),这就是Fortran语言相对简单易学的原因。在Fortran中可以有指针数组,但这是一个完全不同的问题。

M Metcalf和J Reid的《Fortran 90/95 explained》是咨询Fortran语言特性的好参考资料。从第48页开始:

3.11 数组赋值

通过内部赋值,可以将数组表达式分配给相同形状的数组变量,这被解释为如果将表达式的每个元素分配给变量的相应元素。例如,具有如下声明:

real, dimension(10, 20) :: a

这个任务

a = a  + 1.0

i=1,2..,10j=1,2,..,20a(i,j) 替换为 a(i,j)+1.0

此外,请注意,标量表达式可以分配给数组,此时标量值会广播到所有数组元素中

关于实际的实现方式,这完全是Fortran标准未指定的。这种情况未指定,以允许编译器作者进行任何他们认为适合的优化。例如,在赋值语句 a = b 中,Fortran标准未指定将 b 的元素复制到 a 中的顺序,因此不同的编译器可能以不同的方式执行此操作。对于此问题,你需要知道的是,只要 ab 不是指针,则它们是不同的数组,并且更改一个数组的元素不会更改另一个数组的相应元素。因此,在某种意义上,a=b 是一种“深度复制”,你可以将其视为将 b 中的所有项复制到 a 的内存位置。


@IanH 这不是我非常了解的事情,所以我在我的回答中只关注了数组。如果您想发布一个答案,展示派生类型上述情况不适用的例子,那将会很有趣。 - Chris
抱歉那些话语有点啰嗦,那只是一个未完成的思维泡泡,我认为与问题无关(因为发帖人特别提到了REAL变量)。我甚至没有意识到它已经被发布了。 - IanH
2
“b(1:n) = a(1:n)” 和 “b = a” 不是等价的。前者不会检查必要的重新分配,例如。 - Vladimir F Героям слава
@VladimirF,抱歉回复这篇旧帖子,您能否更详细地解释一下“必要的重新分配”是什么意思?谢谢。 - user26143
1
如果左侧的数组未被分配或者已经被分配为不同大小,a = b 将自动将 a 重新分配为与 b 相同的大小。这需要检查它们是否符合规格,但对于 b(1:n) = a(1:n) 则无需进行此操作,因为不会发生任何重新分配。 - Vladimir F Героям слава

11

a = b将整个数组b复制到a中。如果您只想获取n维大于的数组的一部分,则可以使用下标符号a(1:n) = b(1:n)。这是Fortran 90——比FORTRAN 77更高级的语言。我们可以通过该语句使用操作符"=",知道"a = b"是一个复制而不是关联指针a和目标b。指针关联使用=>。

编辑:通过复制,它创建了一个副本,可能与您的do循环具有相同的机器代码。指针关联则是在不执行循环以复制所有数组元素的情况下进行引用。

详见http://en.wikipedia.org/wiki/Fortran_95_language_features


1
它是如何复制的?通过将a的引用指向内存中b的位置,或者通过将b中所有项的副本移动到内存中a的位置? - astay13
4
@astay13,Fortran不是Java或C#。它没有引用(reference)的概念,但有指针(pointers),使用特殊语法来关联,正如M. S. B.所指出的(=>而不是=)。例如,gfortran 使用memcpy (位拷贝,非常快速)或隐藏的DO循环,在上下文中实现数组的复制。 - Hristo Iliev
@HristoIliev,是的,这个问题出现是因为Java是我的第一语言,所以我习惯于用=来进行引用赋值的思考。 - astay13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接