首页 文章

在每个数据类型实例中复制过程

提问于
浏览
0

当我们从具有传递过程指针的数据类型(类)创建多个实例时,是否在每个实例中复制了实际过程(子例程/函数)?或只是复制指针?

例如,请考虑以下编译和运行正确的代码 .

module mod2
  implicit none

  private

  type class_type
     integer :: a, b, c
   contains
     procedure :: add => add_it
  end type class_type

  public :: class_type

contains

  subroutine add_it(this)
    implicit none
    class(class_type), intent(inout) :: this

    this%c = this%a + this%b

  end subroutine add_it

end module mod2

program tester
  use mod2
  implicit none

  type(class_type), dimension(10) :: objs

  objs(:) = class_type(1, 2, 0)

end program tester

从数据类型 class_type 创建的10个对象中的每个对象中是否重复了子程序 add_it ?或者是子程序 add_it 的指令集存储在某处并指向它,即 "procedure :: add => add_it" 复制在每个对象中?

1 回答

  • 1

    通常都没有 . 请注意,这是非常具体的实现 - 我在下面描述的是典型的,但不同的处理器可能会做不同的事情 .

    请注意,示例中没有过程指针 . class_type 类型具有绑定 . 如果 class_type 有一个过程指针,则情况就不同了 .

    绑定的典型实现是编译器创建一个机器级指针表,每个特定绑定有一个条目,指针指向过程的代码 . 为程序中的每种类型创建一个表(有时称为“vtable”,来自用于C和类似语言中的虚拟成员函数的类似技术) .

    对于 polymorphic 对象(用 CLASS 声明的事物),编译器然后创建一个描述符,该描述符具有指向对象的动态(运行时)类型的相关表的机器级指针 . 该指针有效地指示对象的动态类型,并且可以在诸如 SELECT TYPE 之类的构造中使用,并且可以在诸如 SAME_TYPE_AS 之类的东西中进行调用 . 如果你有一个多态数组,编译器最初通常只为整个数组创建一个描述符,因为数组中的各个元素必须都具有相同的动态类型 .

    当您对多态对象调用绑定时,编译器将跟随指向vtable的指针,然后查找指向过程绑定的相关指针 .

    非多态对象(使用TYPE声明的事物)不需要这样的描述符或指针解引用,因为动态和声明的类型总是相同的,编译器知道声明的类型是什么,并且编译器在编译时知道哪个过程将叫做 .

    如果您有一个过程调用,其中非多态实际参数与多态伪参数相关联,那么编译器通常会创建必要的描述符作为进行过程调用的一部分 . 类似地,将多态数组元素传递给采用多态标量的过程 .

    您的代码的主程序不包含多态实体,并且您不调用任何过程,因此可能没有任何机器指针返回到vtable .

    过程指针组件(在类型声明的CONTAINS之前声明为 PROCEDURE(xxx), POINTER :: yyy 的组件)对于每个对象可以是不同的(包括对于数组中的每个元素都不同) . 在这种情况下,典型的实现是将机器级指针存储到相关过程的代码(如果过程指针组件尚未关联,则为空指针) .

相关问题