2

考虑下面的类结构,它涉及三个独立的模块:

!------------------------ 在文件 af 中

  module parent_body_mod
  type :: face
     class(parent_body), pointer :: bPtr
  end type
  type, abstract :: parent_body
     integer i
     type(face) :: f
  end type
  end module parent_body_mod

!------------------------ 在文件 bf 中

  module body_mod
  use parent_body_mod

  type, extends(parent_body) :: body
  end type

  interface body
     procedure :: new_body
  end interface

  contains

  function new_body() result(b) 
  type(body), target :: b
  b%i = 123
  b%f%bPtr => b
  end function
  end module body_mod

!---------------------------- 在文件 cf

  module body_group_mod
  use body_mod
  type :: body_group
     type(body), allocatable :: b
  end type
  interface body_group
     procedure :: new_body_group
  end interface
  contains 
  function new_body_group() result(bg)
  type(body_group) :: bg

  allocate(bg%b)
  bg%b = body()

  end function
  end module body_group_mod

!-------------------- 主程序

  use body_group_mod

  type(body_group) :: my_bg

  my_bg = body_group()      

  print *, my_bg%b%f%bPtr%i

  end

!----------------------------------------

预期的输出是 123,而实际的输出是随机的。该代码使用 ifort 版本 18.0.1 编译。请注意,使用“body”类本身时不会发生相同的问题,即以下工作正常:

type(body), allocatable :: my_b

allocate(my_b)

my_b = body()

print *, my_b%f%bPtr%i ! This produces 123 as expected.

任何帮助表示赞赏。

4

1 回答 1

3

代码不符合要求。

当过程执行完成时,与过程的未保存局部变量关联的指针变为未定义 (F2008 16.5.2.5 (5))。b函数中的函数结果new_body被认为是这样一个局部变量(F2008 1.3.154.1),因此b%f%bPtr函数调用后指针组件变为未定义。

与其他本地未保存的变量相比,函数结果有点特殊,因为它们的值可用时间比变量存在的时间长 - 有关一些讨论,请参见 F2008 Note 12.41。

另一种思考问题的方式是,对于语句bg%b = body(),左侧的身体与右侧的身体是不同的对象。赋值只是复制右手边对象的值——一旦赋值完成,右手边的对象就不复存在了。没有任何代码可以说明当传输主体对象的值时 - 需要更新指针组件以引用分配给的左侧变量。另请注意,左侧bg%b没有 TARGET 属性 - 因此无论如何都无法将指针与其有效关联。

于 2018-07-06T20:52:55.783 回答