指针的Fortran副本 [英] Fortran copy of pointer

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

问题描述

我有一个var类型的变量,它包含一个指针p。
我需要将var复制到与var相同类型的另一个变量var1(通过执行var1=var,因为我不知道它是否是正确的方式,请参见下文)。



在我的实现中,var和var1被传递给需要初始化var1到var的子例程,然后修改var1。
如果我更改了var1%p的值,那么var%p也会被修改。
因此,我需要更改var1%p指向的内存区域的值,而无需修改var%p指向的内存区域。
在Fortran(2003,Intel)中,正确的方法是什么?



代码示例:

 类型变量
实数,维(:),指针:: p
结束类型变量


子例程init (var,var1)!这当然不会工作
类型(变量):: var,var1
var1 = var
结束子程序

现在,我需要能够做一些等同于更改var1%p的内容,而不会影响var%p。我无法更改变量(我正在修改现有的代码)。






以下解决方案(如果我是正确的):
我声明var1为:

 类型(变量),allocatable :: Var1 

然后分配并初始化:

  allocate(var1,source = var)
var1 = var

然后

 调用somesub(var1)

修改var1%p,会导致修改var%p,使var%p等于var1%p。

编辑3:
执行:

  init子程序(var,var1)
类型(变量),intent(in):: var
类型(变量),可分配,intent(inout):: var1
allocate(var1%p,source = var%p)
var1%p = 2
结束子程序init

类型变量:: var
类型变量,allocatable :: var1
调用init(var,var1)

以上编译但崩溃(无限挂起)。
改用:

  allocate(var1,source = var)

运行但将var%p更新为1。

解决方案

<当你对派生类型变量进行内部赋值时,任何指针都会使用指针赋值 => 来复制(它只是复制现有块的地址和其他属性记忆)。您必须确保在内存中分配了新的目标,并将数组的值复制到那里。



您可以为给定类型创建自己的重载分配,而不是使用语法 var1 = var1 ,或者您可以将适当的赋值语句编码到您的子例程中,如果足够:

<$ p $ (var,var1)!这当然不会工作
类型(变量):: var,var1!不要忘记这个举例时间下一次!

allocate(var1%p(lbound(var%p,1):ubound(var%p,1)))

var1%p = var%p
结束子程序

由于HighPerformance Mark评论说,如果您没有其他原因使用指针,可分配组件更好。

 类型变量
实数,维(:),allocatable :: p
end类型变量


子例程init(var,var1)!这样可以工作
类型(变量):: var,var1
var1 = var
结束子程序






在你的编辑中你有同样的问题:

  var1 = var 

与以前完全相同的问题,你没有改变任何东西!



另外

  allocate(var1,source = var)

应该与原始代码具有相同的效果,我相信你需要

  allocate(var1%p,source = var%p) 

但我已经评论过,最常见的gfortran版本不会接受,并且需要明确指定形状。



变量 var var1 不必是可分配的。但它们可以是,如果由于某些其他原因需要的话。






可以编写一次用户定义的赋值然后重载内部赋值( = )。

 类型变量
real :: pointer :: p(:)
包含
procedure :: assign
generic :: assignment(=)=>分配
结束类型

子程序赋值(出,入)
类(变量),意图(出)::出
类(变量),意图):: in

allocate(out%p(lbound(in%p,1):ubound(in%p,1)))

out%p = in %p
结束子程序

然后你可以写 var1 = var ,它会自动调用子程序 assign


I have a type var that contains a pointer p. I need to copy var on another variable var1 of the same type as var (by doing var1 "=" var, in quotation because I do not know if it is the correct way, see below).

In my implementation var and var1 are passed to a subroutine that needs to initialise var1 to var and then modify var1. If I change the values of var1%p, then var%p is modified as well. So, I need to change the values of the memory zone pointed by var1%p, without modifying the memory zone pointed by var%p. What is the correct way to do that in Fortran (2003, Intel) ?

Code example:

type variable 
     real, dimension(:), pointer:: p
end type variable


subroutine init(var,var1) !This of course will not work
  type (variable):: var, var1
  var1=var
end subroutine

Now, I need to be able to do something equivalent to changing var1%p without affecting var%p. I cannot change variable (I am modifying existing code).


Following solution below (if I am correct): I declare var1 as:

Type(variable), allocatable:: Var1 

then allocate and initialize:

allocate(var1, source=var) 
var1 = var  

Then

call somesub(var1)

that modifies var1%p, has the consequence to modify var%p such that var%p is equal to var1%p.

Edit 3: Doing:

 subroutine init(var,var1)
 type(variable), intent(in):: var
 type(variable), allocatable, intent(inout):: var1
 allocate(var1%p, source=var%p)
 var1%p = 2 
 end subroutine init

 type variable:: var
 type variable, allocatable:: var1
 call init(var, var1)

The above compiles but crashes (hangs infinitely). Using instead:

allocate(var1, source=var) 

runs but updates var%p to 1.

解决方案

When you do an intrinsic assignment of derived type variables, any pointers are copied using pointer assignment => (which just copies the address and other properties of the existing piece of memory). You must make sure a new target is allocated in memory and the value of the array is copied there.

You can create your own overloaded assignment for the given type and than use the syntax var1 = var1, or you can code the proper assignment into your subroutine, if it suffices:

subroutine init(var,var1) !This of course will not work
 type(variable) :: var, var1  !DO NOT FORGET THIS WHEN POSTING EXAMPLES NEXT TIME!

 allocate( var1%p(lbound(var%p,1):ubound(var%p,1)) )

 var1%p = var%p
end subroutine

As HighPerformance Mark commented, if you do not have other reasons to use pointers, allocatable components are MUCH better.

type variable 
     real, dimension(:), allocatable :: p
end type variable


subroutine init(var,var1) !This WILL work
  type (variable):: var, var1
  var1 = var
end subroutine


In your edit you have the same problem:

var1 = var 

That is exactly the same problem as before, you didn't change anything!

Also

allocate(var1, source=var) 

should have the same effect as the original code, I believe you need

allocate(var1%p, source=var%p) 

but I already commented that most common versions of gfortran will not accept that and will require the shape to be specified explicitly.

The variables var and var1 do not have to be allocatable. But they can be, if it is required for some other reason.


It is possible to write the user defined assignment once and then overload the intrinsic assignment (=).

   type variable
     real :: pointer :: p(:)
   contains
     procedure :: assign
     generic :: assignment(=) => assign
   end type

   subroutine assign(out, in)
      class(variable), intent(out) :: out
      class(variable), intent(in) :: in

      allocate( out%p(lbound(in%p,1):ubound(in%p,1)) )

      out%p = in%p
   end subroutine

Then you can write var1 = var whenever you want and it will call the subroutine assign automatically.

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

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