以下是我过去几天遇到的问题。假设您有以下结构:
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
和lesserStruct
重新分配给更大的尺寸。所以我做了以下几点:
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)
就像一个魅力:所有指针都被正确复制,我可以访问lesserStruct(.)%ptr
中所有元素的1:lesserSize
。
但是,如果我尝试对其他结构做同样的事情:
ALLOCATE(tempSuperStruct(superSize + newSuperSize))
tempSuperStruct(1:superSize) = superStruct(1:superSize)
CALL MOVE_ALLOC(tempSuperStruct, superStruct)
然后我再也无法访问lesserStruct(.)%ptr
了。我发现这是因为=
的行。请注意,如果我改为:
CALL MOVE_ALLOC(superStruct,tempSuperStruct)
我仍然可以访问lesserStruct(.)%ptr
,因为正如标准中所述:If to has the TARGET attribute, any pointer associated with from at the time of the call to MOVE_ALLOC becomes correspondingly associated with to.
不幸的是,我之后仍然需要执行=
步骤,在此期间我失去指针关联
所以这是我的问题:有没有办法以“MOVE_ALLOC方式”复制我的结构,所以与它相关的指针会自动跟随?更一般地说,是否有更好的解决方案来扩展我的结构的大小?
提前致谢!
答案 0 :(得分:2)
我认为你误解了MOVE_ALLOC的使用。
当您使用临时allocatable和MOVE_ALLOC重新分配lesserStruct时,事实上,您正在保留指针,这就是为什么您仍然可以在此步骤之后使用它们。
在第二步中,当您使用临时allocatable和MOVE_ALLOC重新分配superStruct时,您正在改变superStruct存储其值的内存位置。
在步骤2中,当你简单地做一个
时CALL MOVE_ALLOC(superStruct,tempSuperStruct)
你正在做的是传递" superStruct"到" tempSuperStruct"。现在,superStruct被释放,tempSuperStruct现在保存已分配的空间。但是如果你看一下,你会发现它只有超级大小的'元素,而不是superSize + newSuperSize'。 lesseStruct仍然有效(至少对于superSize元素),因为到达where的内存空间仍然以相同的方式使用。
因此,您误解标准的原因是,如果具有TARGET属性,则与FROM关联的任何指针都将与TO关联。在您的情况下,任何指针与" tempSuperStructure"那就是你的FROM将在MOVE_ALLOC之后与superStructure相关联,而不是来自lesserStruct的指针......
请参阅?
在你的情况下,我看到的唯一方法是在重新分配lesserStruct之后重新分配指向superStruct元素的指针。
答案 1 :(得分:1)
不 - 您需要重新考虑您的方法。
如果指针始终与特定数组中的元素相关联(这似乎就是这种情况),那么您只需存储感兴趣元素的索引即可。 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)