问题描述
我有一个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副本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!