[英]Pointers to arrays as member variables in Fortran derived type
Fortran 无法将派生类型的成员变量作为目标。 (我想这与未指定派生类型如何存储在 memory 中的标准有关?)但是,我可以将指针作为成员变量并将指针与指针相关联。 就像我在下面的例子中所做的那样。
module DataMod
type DataType
real(8), private, dimension(:,:), pointer, contiguous :: A
real(8), private, dimension(:,:), pointer, contiguous :: B
integer :: n
contains
procedure :: alloc
procedure :: set
procedure :: print_
final :: dealloc
end type DataType
interface DataType
procedure :: NewDataType
end interface DataType
contains
function NewDataType(dimension_) result(new)
integer, intent(in) :: dimension_
type(DataType) :: new
new%n = dimension_
end function NewDataType
subroutine alloc(dataObject)
class(DataType) :: dataObject
allocate(dataObject%A(dataObject%n,dataObject%n))
allocate(dataObject%B(dataObject%n,dataObject%n))
end subroutine alloc
subroutine set(dataObject, datas, choice)
class(DataType) :: dataObject
real(8), dimension(dataObject%n,dataObject%n), intent(in) :: datas
character(len=1), intent(in) :: choice
real(8), dimension(:,:), pointer :: dataPointer
integer :: i,j
if(choice .eq. 'A') then
datapointer => dataObject%A
elseif(choice .eq. 'B') then
datapointer => dataObject%B
else
stop
endif
do j = 1,dataObject%n
do i = 1,dataObject%n
datapointer(i,j) = datas(i,j)
enddo
enddo
end subroutine set
subroutine print_(dataObject)
class(DataType), intent(in) :: dataObject
print *, 'A'
print *, dataObject%A(1:dataObject%n,1:dataObject%n)
print *
print *, 'B'
print *, dataObject%B(1:dataObject%n,1:dataObject%n)
end subroutine print_
subroutine dealloc(dataObject)
type(DataType) :: dataObject
deallocate(dataObject%A)
deallocate(dataObject%B)
end subroutine dealloc
end module DataMod
program DataTest
use DataMod, only: DataType
implicit none
real(8), dimension(2,2) :: testArray
type(DataType) :: testType
testType = DataType(2)
call testType%alloc()
testArray(1,1) = 1
testArray(2,1) = 2
testArray(1,2) = 3
testArray(2,2) = 4
call testType%set(testArray, 'A')
testArray(1,1) = 5
testArray(2,1) = 6
testArray(1,2) = 7
testArray(2,2) = 8
call testType%set(testArray, 'B')
call testType%print_()
end program DataTest
在 set 例程中,我使用一个 if 语句来设置一个指针,以决定它是否应该将传入的矩阵转储到 A 或 B 中。在我目前正在处理的程序中,我必须决定将四个不同矩阵的哪个组合相乘并且设置一对指针比编写 16 个几乎相同的 dgemm 调用要好得多。
我的问题是,除了悬挂指针等的正常危险之外,这种方法是否还有任何问题,或者没有指针就可以做到这一点? 不应从 object 外部访问 arrays。是否存在任何性能问题?
类型定义中的组件可能不使用 TARGET 属性声明(除了缺少语法,这将与当前语言中的其他概念和规则不一致),但如果派生类型的变量具有 TARGET 属性,则其所有子对象也有 TARGET 属性。 对于类型定义:
type DataType
real(8), private, dimension(:,:), allocatable :: A
real(8), private, dimension(:,:), allocatable :: B
...
程序集可以写成...
subroutine set(dataObject, datas, choice)
class(DataType), TARGET :: dataObject
real(8), dimension(dataObject%n,dataObject%n), intent(in) :: datas
character(len=1), intent(in) :: choice
real(8), dimension(:,:), pointer :: dataPointer
! require dataobject%A and ..%B to already be allocated.
if(choice .eq. 'A') then
datapointer => dataObject%A
elseif(choice .eq. 'B') then
datapointer => dataObject%B
else
stop
endif
datapointer = datas ! or some other operation.
...
( dataPointer
可以声明为连续的,它指向的可分配 arrays 始终是连续的。)
没有 TARGET 属性的实际参数可能与具有 TARGET 属性的伪参数相关联。 如果是这种情况,则与伪参数关联的指针在过程执行完成时变为未定义。 (在某些情况下,此类指针也可能变得未定义,即使实际参数具有 TARGET 属性 - 有关详细信息,请参阅 F2018 15.5.2.4p8 - 但这些情况不适用于标量。)
因此,在一般情况下,如果指向派生类型 object 的组件之一的指针需要比上面set
的过程更长寿(例如,如果dataPointer
不是set
的本地对象)并且您不能确保实际参数将始终具有 TARGET 属性,那么使用指针组件的原始方法可能更合适。 问题中的实现似乎没问题——尽管我建议使终结器 IMPURE ELEMENTAL 使事情对未来的变化更加稳健。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.