gpt4 book ai didi

oop - Fortran 构造函数返回指向已分配对象的指针

转载 作者:行者123 更新时间:2023-12-05 05:05:28 29 4
gpt4 key购买 nike

在这个问题中:Fortran Functions with a pointer result in a normal assignment ,声明不推荐返回指针的函数。

我的问题涉及用户定义类型的构造函数。考虑以下代码:

program PointTest

use PointMod, only: PointType

implicit none

class(PointType), allocatable :: TypeObject

TypeObject = PointType(10)

end program PointTest
module PointMod

implicit none

type PointType

real(8), dimension(:), allocatable :: array

contains

final :: Finalizer

end type PointType

interface PointType

procedure NewPointType

end interface PointType


contains


function NewPointType(n) result(TypePointer)

implicit none

integer, intent(in) :: n

type(PointType), pointer :: TypePointer

allocate(TypePointer)

allocate(TypePointer%array(n))

end function NewPointType


subroutine Finalizer(this)

implicit none

type(PointType) :: this

print *, 'Finalizer called'

end subroutine Finalizer


end module PointMod

在代码中,我定义了一个带有构造函数的类型,它分配对象,然后在对象中分配一个数组。然后它返回一个指向该对象的指针。

如果构造函数刚刚返回对象,对象和数组将被复制然后释放(至少对于标准兼容的编译器)。这可能会导致开销并扰乱我们的内存跟踪。

使用 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 = PointType(10)

作用是它复制存储在指针中的对象的值。然后指针被遗忘,指针指向的内存被泄漏并永远丢失。


你写“据我所知,不会有悬空指针,我们将对何时分配对象有更多控制。”但是,我看不出有什么方法可以避免函数内部分配的悬挂指针。即使是终结器也无济于事。我也看不出你有更多的控制权。您显式分配的内存刚刚丢失。您对 TypeObject 有不同的内存(可能在主程序的堆栈上),并且类型内的数组将在内部赋值复制期间再次分配 TypeObject = PointType(10).

终结器可以处理数组组件,因此函数内部分配的数组不必丢失。然而,指针 TypePointer 指向的类型本身,及其不可分配的非指针组件和描述符等,不能从终结器中释放,并且将保持悬空状态,内存将泄露。


不要害怕将对象作为值返回的函数。那不是问题。编译器很聪明,能够优化不必要的副本。编译器可能很容易发现您只是在分配函数结果,因此它可以将分配目标的内存位置用于函数结果变量(如果它不必是可分配的)。

存在许多其他优化。

   function NewPointType(n) result(TypePointer)   
integer, intent(in) :: n

type(PointType) :: TypePointer

allocate(TypePointer%array(n))
end function NewPointType

更简单,应该可以正常工作。通过优化,它甚至可以更快。如果无法使用非指针不可分配的结果,请使用可分配的。不要对函数结果使用指针。

关于oop - Fortran 构造函数返回指向已分配对象的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60507302/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com