指针的 Fortran 副本

3 memory fortran pointers

我有一个包含指针 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。

Vla*_*r F 5

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

您可以为给定类型创建自己的重载赋值,然后使用语法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 不会接受这一点,并且需要明确指定形状。

变量varvar1不必是可分配的。但如果出于其他原因需要,它们可以是。


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

   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自动调用子程序。