指针作为虚拟参数 [英] pointer as a dummy argument

查看:123
本文介绍了指针作为虚拟参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对以下程序感到有些困惑

I am somewhat puzzled by the following program

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

及其派生词.以后再说.众所周知,Fortran会将例程参数作为传递引用进行传递,这意味着在foobar的虚拟参数test处出现的实体与在program hello中的堆栈上授予的内存空间相同.到目前为止一切顺利.

and its derivatives. More on those later. As we know, Fortran transfers routine arguments as a pass-by-reference, meaning that the entity emerging at the dummy argument test for both foo and bar is the same memory space granted on the stack in program hello. So far so good.

假设我在program hello中将type(TestType) :: t定义为指针,并对其进行分配.

Suppose I define in program hello the type(TestType) :: t as a pointer, and allocate it.

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

代码像以前一样工作,唯一的区别是对象不是分配在堆栈上,而是分配在堆上.

The code works as before, the only difference being that the object was not allocated on the stack, but on the heap.

现在假定返回堆栈分配的程序,并将该子例程栏定义为

Now assume to go back to the stack-allocated program and that subroutine bar is instead defined as

 subroutine bar(test)
    type (TestType), pointer :: test
    test%i = 6 
 end subroutine

该程序不再编译,因为必须使用堆分配的版本才能正常工作,或者更准确地说,当例程被定义为接受指针作为虚拟对象时,必须将指针传递给例程争论.另一方面,如果dummy参数不包含pointer关键字,则该例程将接受指针和非指针.

The program does not compile anymore because you must use the heap-allocated version to make it work, or to be more accurate it is mandatory to pass a pointer to the routine when the routine is defined to accept a pointer as a dummy argument. On the other hand, if the dummy argument does not contain the pointer keyword, the routine would accept both pointers and non-pointers.

这让我想知道...将虚拟参数声明为指针有什么意义?

This makes me wonder... what's the point of declaring a dummy argument a pointer ?

推荐答案

Tobias Burns的答案来自comp.lang.fortran:

现在假设返回堆栈分配程序,并且 子例程栏改为定义为

Now assume to go back to the stack-allocated program and that subroutine bar is instead defined as

子例程栏(测试) 类型(TestType),指针::测试 测试%i = 6 结束子程序

subroutine bar(test) type (TestType), pointer :: test test%i = 6 end subroutine

该程序不再编译,因为您必须使用 堆分配的版本以使其正常工作,

The program does not compile anymore because you must use the heap-allocated version to make it work,

那不是很正确:您也不能传递ALLOCATABLE变量 具有POINTER属性的虚拟对象.我认为一个(实际的)原因是 指针地址可以转义,从而导致别名 问题.正式的原因是,ALLOCATABLE根本不是 指针;此外,该标准没有讨论堆与栈 与静态内存.实际上,[具有恒定范围]的局部数组将 通常在静态内存中而不是在堆栈中创建(除非您使用 OpenMP或RECURSIVE属性).因此,您的堆栈"示例可以 也可以是静态内存"示例,具体取决于编译器和 使用的选项.

That's not quite correct: You can also not pass an ALLOCATABLE variable to a dummy with POINTER attribute. I think one (practical) reason is that the pointer address can escape and you would thus cause alias problems. A formal reason is that an ALLOCATABLE is simply not a POINTER; additionally, the standard does not talk about heap vs. stack vs. static memory. And in fact, local arrays [with constant bounds] will often be created in static memory and not on the stack (unless you use OpenMP or the RECURSIVE attribute). Thus, your "stack" example could also be a "static memory" example, depending on the compiler and the used options.

或更准确地说是 定义例程时必须将指针传递给例程 接受指针作为虚拟参数.

or to be more accurate it is mandatory to pass a pointer to the routine when the routine is defined to accept a pointer as a dummy argument.

那也不是完全正确的.在Fortran 2008中,您可以通过 non-POINTER,具有TARGET属性,指向一个指针虚拟对象, 具有INTENT(IN)属性. (指针意图是相对于指针而言的 关联状态;对于非指针假人,意图是关于 值存储在变量中.)

That's also not completely true. In Fortran 2008 you can pass a non-POINTER, which has the TARGET attribute, to a pointer dummy which has the INTENT(IN) attribute. (Pointer intent is relative to the pointer association status; for non-pointer dummies the intents are about the value stored in the variable.)

这让我想知道...声明一个虚拟参数有什么意义? 指针?

This makes me wonder... what's the point of declaring a dummy argument a pointer ?

好吧,如果参数具有POINTER属性,则可以分配和 释放指针目标,您可以将指针与某个目标关联 等等.直到Fortran 95为止,不可能有ALLOCATABLE虚拟对象 因此,如果必须要使用(虚拟)参数,则必须使用指针 在过程中分配.

Well, if the argument has the POINTER attribute, you can allocate and free the pointer target, you can associate the pointer with some target etc. Up to Fortran 95 it was not possible to have ALLOCATABLE dummy arguments thus a pointer had to be used if a (dummy) argument had to be allocated in a procedure.

如果可以的话,应该尝试使用ALLOCATABLEs而不是POINTERs- 它们更易于使用,不会泄漏内存并且不会摆姿势 别名分析问题交给编译器.另一方面,如果你想 要创建(例如)链表,您需要一个指针. (尽管,对于一堆 用法,也可以使用Fortran 2008的可分配组件.*)

If you can, you should try to use rather ALLOCATABLEs than POINTERs - they are easier to use, do not leak memory and have pose no alias-analysis problems to the compiler. On the other hand, if you want to create, e.g., a linked list, you need a pointer. (Though, for a heap usage, also Fortran 2008's allocatable components could be used.*)

*I mean:
   type t
       type(t), allocatable :: next
   end type

其中组件的类型与所定义的类型相同; 在F2008之前,只允许使用指针,而不允许分配指针.

where the component is of the same type as the type being defined; before F2008 this was only allowed for pointers but not for allocatables.

和R. Maine

我们知道,Fortran将常规参数作为 引用传递

As we know, Fortran transfers routine arguments as a pass-by-reference,

那么,我们显然不正确地知道.该标准从未规定 并且确实在避免此类规范方面大有作为. 尽管您是一个普遍的误解,但并不完全正确 即使在大多数较旧的编译器中,尤其是在启用优化功能的情况下. 严格的按引用传递将杀死许多常见的优化.

We apparently know incorectly, then. The standard never specifies that and, indeed goes quite a lot out of its way to avoid such specification. Although yours is a common misconception, it was not strictly accurate even in most older compilers, particularly with optimization turned on. A strict pass-by-reference would kill many common optimizations.

使用最新标准,在某些情况下几乎禁止通过引用 案件.该标准在其规范文本中未使用这些词,但 有些事情是无法实现的 通过引用.

With recent standards, pass-by-reference is all but disallowed in some cases. The standard doesn't use those words in its normative text, but there are things that would be impractical to implement with pass-by-reference.

当您开始接触指针之类的东西时,错误的假设 一切都是通过引用传递的,将使自己变得更加强大 比以前明显.您必须放弃那种误解或很多误解 事情会让你困惑.

When you start getting into things like pointers, the error of assuming that everything is pass-by-reference will start making itself more evident than before. You'll have to drop that misconception or many things wil confuse you.

我认为其他人已经充分回答了该帖子的其余部分.一些 也解决了上述问题,但我想强调一下.

I think other people have answered the rest of the post adequately. Some also addressed the above point, but I wanted to emphasize it.

希望这能回答您的问题.

这篇关于指针作为虚拟参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆