Ste*_*ini 2 pointers fortran90
我对以下程序有些困惑
module test
implicit none
type TestType
integer :: i
end type
contains
subroutine foo(test)
type (TestType), intent(out) :: test
test%i = 5
end subroutine
subroutine bar(test)
type (TestType), intent(out) :: test
test%i = 6
end subroutine
end module
program hello
use test
type(TestType) :: t
call foo(t)
print *, t%i
call bar(t)
print *, t%i
end program hello
Run Code Online (Sandbox Code Playgroud)
及其衍生物。稍后再谈。正如我们所知,Fortran语言传递程序参数作为一个传递引用,这意味着实体出现在伪参数test两者foo与bar被许可的堆栈上相同的内存空间program hello。到现在为止还挺好。
假设我在program hello中定义type(TestType) :: t为一个指针,并分配它。
program hello
use test
type(TestType), pointer :: t
allocate(t)
call foo(t)
print *, t%i
call bar(t)
print *, t%i
deallocate(t)
end program hello
Run Code Online (Sandbox Code Playgroud)
代码和以前一样工作,唯一的区别是对象不是在堆栈上分配,而是在堆上。
现在假设回到堆栈分配的程序,并且子程序 bar 被定义为
subroutine bar(test)
type (TestType), pointer :: test
test%i = 6
end subroutine
Run Code Online (Sandbox Code Playgroud)
该程序不再编译,因为您必须使用堆分配版本才能使其工作,或者更准确地说,当例程被定义为接受指针作为虚拟参数时,必须将指针传递给例程。另一方面,如果虚拟参数不包含pointer关键字,则例程将接受指针和非指针。
这让我想知道......将一个虚拟参数声明为指针有什么意义?
转自 comp.lang.fortran,Tobias Burns 的回答:
现在假设回到堆栈分配的程序,并且子程序 bar 被定义为
子程序 bar(test) 类型 (TestType), 指针 :: test test%i = 6 结束子程序
该程序不再编译,因为您必须使用堆分配版本才能使其工作,
这不太正确:您也不能将 ALLOCATABLE 变量传递给具有 POINTER 属性的虚拟变量。我认为一个(实际的)原因是指针地址可以转义,因此会导致别名问题。一个正式的原因是 ALLOCATABLE 根本不是指针;此外,该标准没有讨论堆与堆栈与静态内存。事实上,本地数组 [具有常量边界] 通常会在静态内存中创建,而不是在堆栈中(除非您使用 OpenMP 或 RECURSIVE 属性)。因此,您的“堆栈”示例也可能是“静态内存”示例,具体取决于编译器和使用的选项。
或者更准确地说,当例程被定义为接受指针作为虚拟参数时,必须将指针传递给例程。
这也不完全正确。在 Fortran 2008 中,您可以将具有 TARGET 属性的非 POINTER 传递给具有 INTENT(IN) 属性的指针虚拟对象。(指针意图与指针关联状态相关;对于非指针虚拟对象,意图与存储在变量中的值有关。)
这让我想知道......将一个虚拟参数声明为指针有什么意义?
好吧,如果参数具有 POINTER 属性,您可以分配和释放指针目标,您可以将指针与某个目标等相关联。在 Fortran 95 之前,不可能有 ALLOCATABLE 虚拟参数,因此必须使用指针,如果必须在过程中分配(虚拟)参数。
如果可以,您应该尝试使用 ALLOCATABLE 而不是 POINTER - 它们更易于使用,不会泄漏内存并且不会对编译器造成别名分析问题。另一方面,如果你想创建一个链表,你需要一个指针。(不过,对于堆使用,也可以使用 Fortran 2008 的可分配组件。*)
*I mean:
type t
type(t), allocatable :: next
end type
Run Code Online (Sandbox Code Playgroud)
其中组件的类型与定义的类型相同;在 F2008 之前,这仅允许用于指针,但不允许用于可分配项。
和 R. 缅因州
正如我们所知,Fortran 将例程参数作为传递引用传输,
那么,我们显然不正确地知道。该标准从未规定这一点,而且确实采取了很多措施来避免这种规定。尽管您的误解是一种常见的误解,但即使在大多数较旧的编译器中,它也不是严格准确的,尤其是在启用优化的情况下。严格的引用传递会杀死许多常见的优化。
根据最近的标准,在某些情况下几乎不允许传递引用。该标准在其规范性文本中没有使用这些词,但有些事情通过引用传递来实现是不切实际的。
当你开始研究指针之类的东西时,假设一切都是通过引用传递的错误将开始变得比以前更加明显。你必须放弃这种误解,否则很多事情会让你感到困惑。
我认为其他人已经充分回答了帖子的其余部分。有些人也谈到了上述问题,但我想强调一下。
希望这能回答你的问题。