memory - fortran 函数是否总是将 retun 值的结果复制到接受变量中?
问题描述
mac osx catalina (latest)
gfortran 9.2
fortran standard "gnu"
通过类似下面的代码,我了解到,至少在这种情况下,在函数中构造get_number
了result
值,然后将结果复制到接收变量。可能我也通过在该函数中以一个局部变量为目标的指针做了一个禁忌,但也许编译器对我很好,没有释放一个局部变量,所以我的指针仍然没问题。
我的问题是,这就是所有函数调用的行为方式,即在内存中构造值(无论是简单类型还是复杂类型),然后将值复制过来并丢弃原始结果?我的印象是接收函数调用值的变量只是被赋予了构造结果的内存。
假设我觉得大量的内存复制很浪费,或者假设像下面的代码那样它破坏了我的代码,并且我想在执行许多函数调用时避免它。是用子程序调用替换它们的解决方案吗?但我喜欢函数调用。如果内存复制是正常发生的,有没有办法在进行函数调用时避免内存复制?
module nums
type number
real :: n
end type number
type number_parent
type(number), pointer :: p
contains
procedure, pass(this) :: get_number
end type number_parent
contains
function get_number(this) result(n)
class(number_parent) :: this
type(number), allocatable, target :: n
allocate(n)
n%n = 1.0
this%p => n
end function get_number
end module nums
program main
use nums
implicit none
type(number) :: n
type(number_parent) :: np
n = np%get_number()
print *, n%n
print *, np%p%n
n%n = n%n + 1.0
print *, n%n
print *, np%p%n
end program main
程序输出
> ./a.out
1.00000000
1.00000000
2.00000000
1.00000000
解决方案
我理解你的问题是关于一个叫做返回值优化的东西,你主要是在考虑简单的变量,非指针,不可分配。我的回答只会触及这些。我还将假设没有高级派生类型特性,如多态性和终结性。
我还将假设您仅在简单的分配中使用该功能。当然,函数通常可以出现在许多复杂的表达式中。
从函数返回简单变量时
integer :: ext
ext = func(1)
contains
integer function func(loc) result(res)
res = loc + 1
end function
end
那么从概念上讲,局部变量用于返回值res
,其值将在赋值后复制到外部变量。
在实践中,如果确实使用了一个单独的变量,它将被分配到堆栈上(这没有任何成本,不仅仅是几乎没有,真的没有)。堆可用于大型对象(主要是数组),编译器通常对此进行设置,但普通变量将在堆栈上。然后,当函数返回时,该值被复制到外部变量的位置ext
并重置堆栈指针(这只是意味着其他函数或子例程稍后将使用该内存)。
复制确实会花费一些东西,它可能会或可能不会可以忽略不计。编译器通常能够对此进行优化并使函数ext
直接使用外部变量作为其结果变量res
,因此无需复制。但是,要查看它是否发生,您必须检查编译器生成的机器代码/程序集(或者,如果可用,任何中间表示)。它可能会根据优化级别 ( -O1
, -O2
, -O3
) 和源代码中函数调用的确切上下文而有所不同。
推荐阅读
- javascript - 如何使用 redux-toolkit 中的 createSlice 方法在不同的 reducer 函数中使用单个动作类型
- android - 如果我在 AndroidManifest.xml 中进行更改,我应该如何为应用应用更改?
- c++ - Boost Spirit X3:跳过什么都不做的解析器
- swupdate - 如何对 swupdate Web 界面实施身份验证(用户/密码)
- java - Java binarySearch 找不到所有字符
- python - 为什么我的代码返回随机字母标记,而不是单词标记?
- java - 将 node.js 应用程序作为依赖项添加到 java maven 项目
- c - else if 和 else {if} 的区别
- java - 如何生成、编译、jar、依赖一个gradle模块
- regex - “至少包含以下字母之一”类型的正则表达式问题