Fortran:复制新目标时自动将指针重新分配给新目标
这是我最近几天遇到的问题的一个例子。假设您具有以下结构:Fortran:复制新目标时自动将指针重新分配给新目标,fortran,Fortran,这是我最近几天遇到的问题的一个例子。假设您具有以下结构: TYPE superImportant INTEGER(C_INT) :: one END TYPE superImportant TYPE lessImportant TYPE(superImportant), POINTER :: ptr END TYPE lessImportant TYPE(superImportant), DIMENSION(:), ALLOCATABLE, TARGET :: superS
TYPE superImportant
INTEGER(C_INT) :: one
END TYPE superImportant
TYPE lessImportant
TYPE(superImportant), POINTER :: ptr
END TYPE lessImportant
TYPE(superImportant), DIMENSION(:), ALLOCATABLE, TARGET :: superStruct
TYPE(lessImportant), DIMENSION(:), ALLOCATABLE :: lesserStruct
在代码中的某个点上,superStruct
和lesserStruct
被分配给大小superSize
和lesserSize
,对于lesserStruct
的每个元素,执行类似的操作:
lesserStruct(lesserNumber)%ptr => superStruct(superNumber)
然后,在代码中再进一步,我需要将superStruct
和lesserctruct
重新分配到更大的大小。因此,我做了以下工作:
TYPE(superImportant), DIMENSION(:), ALLOCATABLE, TARGET :: tempSuperStruct
TYPE(lessImportant), DIMENSION(:), ALLOCATABLE :: tempLesserStruct
ALLOCATE(tempLesserStruct(lesserSize + newLesserSize))
tempLesserStruct(1:lesserSize) = lesserStruct(1:lesserSize)
CALL MOVE_ALLOC(tempLesserStruct, lesserStruct)
这就像一个符咒:所有指针都被正确复制,我可以访问1:lesserSize
中所有元素的lesserStruct(.)%ptr
。
但是,如果我尝试对其他结构执行相同操作:
ALLOCATE(tempSuperStruct(superSize + newSuperSize))
tempSuperStruct(1:superSize) = superStruct(1:superSize)
CALL MOVE_ALLOC(tempSuperStruct, superStruct)
然后我无法再访问lesserStruct(.%ptr
。我确定这是因为=
的行。请注意,如果我这样做:
CALL MOVE_ALLOC(superStruct,tempSuperStruct)
我仍然可以访问lesserStruct(.)%ptr
,因为,正如标准中所说:如果to具有TARGET属性,则调用MOVE\u ALLOC时与from关联的任何指针都会相应地与to关联。
不幸的是,在此之后我仍然必须执行=
步骤,在此期间,我失去了指针关联
所以我的问题是:有没有一种方法可以以“MOVE_ALLOC”的方式复制我的结构,这样与它相关的指针就会自动跟随?更一般地说,是否有更好的解决方案来扩展我的结构的大小
提前谢谢 我认为你误解了MOVE\u ALLOC的用法 当您使用临时可分配和MOVE_ALLOC重新分配lesserStruct时,实际上,您保留了指针,这就是为什么在此步骤之后仍然可以使用它们的原因 在第二步中,当您使用临时可分配和MOVE_ALLOC重新分配上层结构时,您正在更改上层结构存储其值的内存位置 当,在步骤2中,你做了一个简单的
CALL MOVE_ALLOC(superStruct,tempSuperStruct)
您所做的是将分配从“上层建筑”传递到“临时上层建筑”。现在,superStruct被释放,tempSuperStruct现在持有分配的空间。但如果你仔细观察它,你会发现它只有“superSize”元素,而没有“superSize+newSuperSize”。lesseStruct仍然有效(至少对于superSize元素),因为指向where is点的内存空间仍然以相同的方式使用
因此,您误解该标准的原因是,如果与FROM关联的指针具有TARGET属性,那么它将与TO关联。在您的情况下,与“tempSuperStructure”相关联的任何指针都将在MOVE_ALLOC之后与上层结构相关联,而不是lesserStruct中的指针
看到了吗
在您的情况下,我看到的唯一方法是在重新分配lesserStruct之后,将指针重新分配给上层结构的元素。否-您需要重新考虑您的方法 如果指针总是与特定数组中的元素相关联(这里似乎就是这种情况),那么您可以只存储感兴趣的元素的索引。Fortran对数组和数组索引操作有很好的支持,因此您最好利用这种支持 另一种方法是将目标数组的各个元素保持为永久标量对象,当您展开目标数组时,这些对象实际上不会移动,而不会赋值
TYPE superImportant
INTEGER(C_INT) :: one
END TYPE superImportant
TYPE superImportantWrapper
! Using a pointer to reference the object, because
! it ensures the target is a TARGET, and simplifies
! assignment. ALLOCATABLE is also a possibility,
! with other changes.
TYPE(superImportant), POINTER :: item => NULL()
CONTAINS
! Elided code to deallocate the item component.
FINAL :: wrapper_Final
END TYPE supertImportantWrapper
TYPE lessImportant
TYPE(superImportant), POINTER :: ptr
END TYPE lessImportant
! The super array is of the wrapper type.
TYPE(superImportantWrapper), DIMENSION(:), ALLOCATABLE, TARGET &
:: superStruct
TYPE(lessImportant), DIMENSION(:), ALLOCATABLE :: lesserStruct
! Elided code to populate each scalar component of the wrapper type.
DO i = 1, xxx ; ALLOCATE(superStruct(i)%item) ; ... ; END DO
! Point at the component, not the wrapper object.
lesserStruct(lesserNumber)%ptr => superStruct(superNumber)%item
...
! Time to grow? Again, array operations on the wrapper.
TYPE(superImportantWrapper), DIMENSION(:), ALLOCATABLE, TARGET :: tempSuperStruct
ALLOCATE(tempSuperStruct(superSize + newSuperSize))
! Intrinsic assignment of the pointer component means it maintains
! the reference to the same object that lesser struct is referencing.
tempSuperStruct(1:superSize) = superStruct(1:superSize)
CALL MOVE_ALLOC(tempSuperStruct, superStruct)