我有一个包含指针 p 的类型 var。我需要在与 var 相同类型的另一个变量 var1 上复制 var (通过做 var1 "=" var, 在引号中,因为我不知道它是否是正确的方法,见下文)。
在我的实现中,var 和 var1 被传递给一个需要将 var1 初始化为 var 然后修改 var1 的子例程。如果我更改 var1%p 的值,那么 var%p 也会被修改。所以,我需要改变var1%p指向的内存区域的值,而不修改var%p指向的内存区域。在 Fortran (2003, Intel) 中这样做的正确方法是什么?
代码示例:
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
Run Code Online (Sandbox Code Playgroud)
现在,我需要能够做一些相当于改变 var1%p 而不影响 var%p 的事情。我无法更改变量(我正在修改现有代码)。
以下解决方案(如果我是正确的):我将 var1 声明为:
Type(variable), allocatable:: Var1
Run Code Online (Sandbox Code Playgroud)
然后分配和初始化:
allocate(var1, source=var)
var1 = var
Run Code Online (Sandbox Code Playgroud)
然后
call somesub(var1)
Run Code Online (Sandbox Code Playgroud)
修改 var1%p 的结果是修改 var%p 使得 var%p 等于 var1%p。
编辑3:做:
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)
Run Code Online (Sandbox Code Playgroud)
以上编译但崩溃(无限挂起)。改用:
allocate(var1, source=var)
Run Code Online (Sandbox Code Playgroud)
运行但将 var%p 更新为 1。
当您对派生类型变量进行内部赋值时,任何指针都使用指针赋值进行复制=>
(它只复制现有内存的地址和其他属性)。您必须确保在内存中分配了一个新目标,并将数组的值复制到那里。
您可以为给定类型创建自己的重载赋值,然后使用语法var1 = var1
,或者您可以将正确的赋值编码到您的子例程中,如果它足够的话:
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
Run Code Online (Sandbox Code Playgroud)
正如 HighPerformance Mark 评论的那样,如果您没有其他理由使用指针,可分配组件会更好。
type variable
real, dimension(:), allocatable :: p
end type variable
subroutine init(var,var1) !This WILL work
type (variable):: var, var1
var1 = var
end subroutine
Run Code Online (Sandbox Code Playgroud)
在您的编辑中,您遇到了同样的问题:
var1 = var
Run Code Online (Sandbox Code Playgroud)
这和之前的问题完全一样,你没有改变任何东西!
还
allocate(var1, source=var)
Run Code Online (Sandbox Code Playgroud)
应该和原代码效果一样,相信你需要
allocate(var1%p, source=var%p)
Run Code Online (Sandbox Code Playgroud)
但我已经评论过,大多数常见版本的 gfortran 不会接受这一点,并且需要明确指定形状。
变量var
和var1
不必是可分配的。但如果出于其他原因需要,它们可以是。
可以编写一次用户定义的赋值,然后重载内部赋值 ( =
)。
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
Run Code Online (Sandbox Code Playgroud)
然后你可以随时写var1 = var
,它会assign
自动调用子程序。