2

正如标题所说,我很好奇“call-by-reference”和“call-by-value-return”之间的区别。我在一些文献中读过它,并试图在互联网上找到更多信息,但我只找到了“按值调用”和“按引用调用”的比较。

我确实理解两者之间在记忆层面的区别,但不是在“概念”层面。

被调用的子例程将拥有它自己的实际参数值的副本来使用,但是当它结束执行时,会将新的本地值(绑定到形式参数)复制回调用者的实际参数。

什么时候按值返回实际上更喜欢“按引用调用”?任何示例场景?我所能看到的是,由于在内存单元中复制值,它需要额外的内存和执行时间。

作为一个附带问题,“按值返回”是否以“现代”语言实现?

4

3 回答 3

3

Call-by-value-return,来自Wikipedia

这种变体在多处理上下文和远程过程调用中引起了人们的注意:如果函数调用的参数是另一个执行线程可以访问的引用,则它的内容可能会被复制到一个新的引用,而不是;当函数调用返回时,这个新引用的更新内容被复制回原始引用(“恢复”)。

因此,在更实际的情况下,变量完全有可能在函数执行过程中处于某种不希望的状态。对于并行处理,这是一个问题,因为您可以尝试访问具有此值的变量。将其复制到临时值可避免此问题。

举个例子:

policeCount = 0

everyTimeSomeoneApproachesOrLeaves()
  calculatePoliceCount(policeCount)

calculatePoliceCount(count)
  count = 0
  for each police official
    count++

goAboutMyDay()
  if policeCount == 0
    doSomethingIllegal()
  else
    doSomethingElse()

假设everyTimeSomeoneApproachesOrLeavesgoAboutMyDay并行执行。

所以如果你通过引用,你最终可能会policeCount在它被设置为 0 后立即得到calculatePoliceCount,即使周围有警察,那么你最终会做一些违法的事情并且可能会进监狱,或者至少咳嗽一些贿赂的钱。如果按值返回传递,则不会发生这种情况。

支持的语言?

在我的搜索中,我发现 Ada 和 Fortran 支持这一点。我不知道其他人。

于 2013-08-22T12:57:52.617 回答
0

假设您有一个引用函数调用(在 C++ 中):

void foobar(int &x, int &y) {
   while (y-->0) {
        x++;
   }
}

你这样称呼它:

int z = 5;
foobar(z, z);

它永远不会终止,因为xy是相同的引用,每次您递减y时,随后都会被递增的 撤消x(因为它们都z在幕后)。

相比之下,使用按值返回的调用(在生锈的 Fortran 中):

subroutine foobar(x,y):
    integer, intent(inout) :: x,y
    do while y > 0:
        y = y - 1
        x = x + 1
    end do
end subroutine foobar

如果您使用相同的变量调用此例程:

integer, z = 5
call foobar(z,z)

它仍然会终止,最后z将更改为 10 或 0,具体取决于首先应用哪个结果(我不记得是否需要特定订单,我找不到任何快速答案网上的问题)。

于 2019-04-25T18:49:31.477 回答
-1

请转到以下链接,那里的程序可以给你一个关于这两个的实用想法。

按引用调用和按值调用之间的区别

于 2013-12-01T07:51:49.097 回答