我有两个派生类型(child1 和 child2),它们都从相同的抽象类型(type, abstract :: parent
)扩展而来。抽象类型有一个延迟绑定(bind)过程。
我想调用一个子程序来执行一些事情(性能关键),具体取决于作为输入移交的 child 的类型。我可以想到两个选择:
class(parent), intent(inout) :: type_in
作为输入。然后在 select type (type_in)
内完成子级的实现。构造。 type(child1), intent(inout) :: type_in
和一个 type(child2), intent(inout) :: type_in
并提供一个显式接口(interface)来重载例程名称。 第一个选项允许在编译时不知道父级扩展的实现,但在我的情况下这不是必需的。它还节省了一些代码行,因为只有一部分代码对 child 来说是不同的。
我的问题是:选项一是否有额外的开销,因为我在编译时知道类型时将输入实现为多态数据?
最佳答案
是的,所谓的虚拟通话会产生额外费用。使用虚拟方法表(在其他语言中调用它)并搜索要调用的正确过程。成本可能与 C++ 中虚函数调用的成本相似,请参阅 https://stackoverflow.com/a/453001/721644
即使在编译时,编译器有时也能够找出绑定(bind)调用了哪个过程。例如,当实际传递的对象是非多态的。 GCC 有两个标志 -fdevirtualize
和 -fdevirtualize-speculatively
(使用 -O2、-O3、-Os 启用)将虚拟调用转换为直接调用。它们也可能适用于 Fortran。
关于fortran - 当类型在编译时已知时,是否有额外的开销调用具有多态派生类型的子例程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32912384/