Oop Fortran构造函数返回指向已分配对象的指针
在这个问题中,声明不建议使用返回指针的函数 我的问题涉及用户定义类型的构造函数。考虑下面的代码:Oop Fortran构造函数返回指向已分配对象的指针,oop,pointers,constructor,fortran,fortran2008,Oop,Pointers,Constructor,Fortran,Fortran2008,在这个问题中,声明不建议使用返回指针的函数 我的问题涉及用户定义类型的构造函数。考虑下面的代码: program PointTest use PointMod, only: PointType implicit none class(PointType), allocatable :: TypeObject TypeObject = PointType(10) end program PointTest 在代码中,我使用构造函数定义了一个类型,该构造函数分配对
program PointTest
use PointMod, only: PointType
implicit none
class(PointType), allocatable :: TypeObject
TypeObject = PointType(10)
end program PointTest
在代码中,我使用构造函数定义了一个类型,该构造函数分配对象,然后在对象中分配数组。然后它返回一个指向该对象的指针
如果构造函数只是返回了对象,那么对象和数组将被复制,然后被释放(至少使用符合标准的编译器)。这可能会导致开销和内存跟踪混乱
使用ifort编译上述代码时,不会使用-warn all发出警告(除了终结器中未使用的变量),代码的行为与我预期的相同。它也适用于gfortran,除非我在使用-Wall时收到警告
TypeObject = PointType(10)
1
Warning: POINTER-valued function appears on right-hand side of assignment at (1) [-Wsurprising]
使用这样的构造函数有什么风险?据我所知,将不会有悬空指针,我们将对何时分配对象有更多的控制。实现相同结果的一种解决方法是显式分配对象,并将构造函数转换为设置变量和分配数组的子例程,但它看起来不那么优雅。还有其他解决办法吗?我们的代码在Fortran 2008标准中。不要使用指针值函数。通常我从不生成返回函数的函数。它们既糟糕又令人困惑。它们会导致令人讨厌的错误,尤其是当人们混淆了
=>
和=
时
该函数所做的是分配一个新对象,并创建一个分配该对象的指针
什么
它的作用是复制存储在指针中的对象的值。然后指针被遗忘,指针指向的内存被泄漏并永远丢失
您可以这样写:“据我所知,将不会有悬空指针,我们将对分配对象的时间有更多的控制。”但是,我没有看到避免在函数内部分配悬空指针的方法。在这里,即使是终结器也帮不上忙。我也看不出你有多大的控制力。您显式分配的内存刚刚丢失。您对
TypeObject
(可能在主程序的堆栈上)有不同的内存,在复制过程中,类型内的数组将在内部赋值TypeObject=PointType(10)
处再次分配
终结器可以处理数组组件,这样就不必丢失在函数中分配的数组。但是,指针TypePointer
指向的类型本身及其不可分配的非指针组件和描述符等无法从终结器中解除分配,并且将保持悬空状态,内存将泄漏
不要害怕将对象作为值返回的函数。这不是问题。编译器非常智能,能够优化不必要的副本。编译器可能很容易发现您只是在分配函数结果,因此它可以使用函数结果变量的分配目标的内存位置(如果它不必是可分配的) 还有许多其他优化
function NewPointType(n) result(TypePointer)
integer, intent(in) :: n
type(PointType) :: TypePointer
allocate(TypePointer%array(n))
end function NewPointType
更简单,应该可以正常工作。通过优化,它甚至可以更快。如果无法使用非指针非可分配结果,请使用可分配结果。不要对函数结果使用指针。如果您担心“如果构造函数刚刚返回了对象,那么对象和数组将被复制”,那么可能值得指出的是,您的代码示例在语句
TypeObject=PointType(10)中对TypeObject
进行了内在赋值
。感谢您的快速回答。我认为该函数将返回指针的副本,指向内存的同一部分。在我们的例子中,我们在运行前不知道对象的确切类型,只知道类,所以最好的方法可能是使用最小的构造函数和单独的子例程来处理较大的分配。@rolf Tje函数确实返回指针。但是,您没有将指针设置为指针(=>
)。您甚至不能进行指针赋值,因为您的TypeObject
未声明为指针。我建议再次阅读你在问题中链接的答案。此外,将类型从函数分配给类变量也没有什么错,这取决于用例。请注意,在Fortran中,对象本身的内存分配及其初始化(包括分配内部的数组companites)是两个完全独立的事情。
TypeObject = PointType(10)
function NewPointType(n) result(TypePointer)
integer, intent(in) :: n
type(PointType) :: TypePointer
allocate(TypePointer%array(n))
end function NewPointType