当前位置: 首页 > 知识库问答 >
问题:

按引用传递和按值传递有什么区别?

昝涛
2023-03-14

两者之间有什么区别

  1. 引用传递的参数
  2. 通过值传递的参数?

你能给我举几个例子吗?

共有1个答案

单于翰飞
2023-03-14

首先,在CS理论中定义的“按值传递与按引用传递”的区别现在已经过时,因为最初定义为“按引用传递”的技术已经失宠,现在很少使用。1

较新的语言2倾向于使用不同(但相似)的一对技术来实现相同的效果(见下文),这是造成混淆的主要原因。

造成混淆的第二个原因是,在“通过引用”中,“引用”的含义比一般术语“引用”的含义要窄(因为该短语早于它)。

现在,真正的定义是:

>

  • 通过引用传递参数时,调用方和被调用方对该参数使用相同的变量。如果被调用方修改了参数变量,则该效果对调用方的变量是可见的。

    当参数按值传递时,调用方和被调用方有两个值相同的独立变量。如果被调用方修改了参数变量,则该效果对调用方不可见。

    在这个定义中需要注意的是:

    >

  • “variable”在这里表示调用方的(局部或全局)变量本身--即,如果我通过引用传递一个局部变量并赋值给它,我将更改调用方的变量本身,而不是例如,如果它是指针,则更改它所指向的任何东西。

    • 这现在被认为是坏的实践(作为隐式依赖项)。因此,几乎所有较新的语言都是完全的,或者几乎完全的通过值传递的。在函数不能返回多个值的语言中,按引用传递现在主要以“output/inout参数”的形式使用。

    “比照而过”中“比照”的含义。与一般的“指代”术语不同的是,这个“指代”是暂时的、隐含的。被调用者基本上得到的是一个“变量”,它与原始变量有某种“相同”。具体如何实现这种效果是不相关的(例如,该语言还可能公开一些实现细节--地址、指针、取消引用--这都是不相关的;如果净效果是这样的话,它就是按引用传递)。

    现在,在现代语言中,变量倾向于“引用类型”(另一个比“按引用传递”更晚的概念,并受其启发),即实际对象数据被单独存储在某个地方(通常在堆上),并且只有对它的“引用”才会保存在变量中并作为参数传递。3

    传递这样的引用属于按值传递,因为从技术上讲,变量的值是引用本身,而不是被引用的对象。然而,对程序的净影响可以与按值传递或按引用传递相同:

    • 如果引用只是取自调用方的变量并作为参数传递,这与按引用传递的效果相同:如果引用的对象在被调用方中发生了变化,调用方将看到变化。
      • 但是,如果持有此引用的变量被重新分配,它将停止指向该对象,因此对此变量的任何进一步操作都将影响它现在所指向的内容。
      • 主叫方只需在呼叫之前制作一份私有副本,然后向被呼叫方提供对该副本的引用。
      • 在某些语言中,某些对象类型是“不可变的”:对它们的任何操作似乎改变了值,实际上创建了一个全新的对象,而不影响原来的对象。因此,将这种类型的对象作为参数传递总是具有按值传递的效果:当需要更改时,将自动为被调用方创建一个副本,而调用方的对象将永远不会受到影响。
        • 在函数式语言中,所有对象都是不可变的。

        正如您可能看到的,这对技术几乎与定义中的技术相同,只是有一个间接级别:只需将“变量”替换为“引用对象”。

        它们没有一个一致的名称,这导致了扭曲的解释,比如“在值是引用的情况下按值调用”。1975年,Barbara Liskov提出了“按对象调用共享”这个术语(或者有时只是“按共享调用”),尽管它从未流行起来。此外,这两个词组都不与原词组平行。难怪旧的术语在没有更好的东西的情况下被重复使用,导致混乱。4

        注:很长一段时间以来,这个答案习惯说:

        说我想和你分享一个网页。如果我告诉你网址,我是通过引用。您可以使用该URL来查看与我所看到的相同的网页。如果那一页被改变了,我们都看到了改变。如果您删除了URL,您所做的只是破坏了对该页面的引用--您并不是删除了实际的页面本身。

        如果我打印出这一页并给你打印出来的,我就是在传递值。您的页面是原始页面的断开副本。您不会看到任何后续更改,并且您所做的任何更改(例如,在打印输出上涂鸦)都不会显示在原始页面上。如果您销毁了打印输出,那么实际上您已经销毁了对象的副本--但原始网页仍然保持完整。

        这基本上是正确的,但“引用”的狭义含义除外--它既是临时的,也是隐式的(它不是必须的,但是显式和/或持久化是附加的特性,不是前面解释的通过引用语义的一部分)。一个更接近的类比就是给你一份文档的副本,而不是邀请你去做文档的原件。

        1除非使用Fortran或Visual Basic编程,否则这不是默认行为,而且在现代使用的大多数语言中,甚至不可能真正的按引用调用。

        2相当多的老版本也支持它

        3在几种现代语言中,所有类型都是引用类型。这种方法在1975年由CLU语言首创,后来被许多其他语言采用,包括Python和Ruby。更多的语言使用混合html" target="_blank">方法,其中一些类型是“值类型”,另一些是“引用类型”--其中包括C#、Java和JavaScript。

        4重复使用一个合适的旧术语本身并没有什么不好,但是你必须弄清楚每次使用的是什么意思。不这样做恰恰会造成混乱。

  •  类似资料:
    • 本文向大家介绍什么是PHP中的按引用传递和按值传递?,包括了什么是PHP中的按引用传递和按值传递?的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将学习PHP中的按值传递和按引用传递。  现在,让我们详细了解这两个概念。 通常,在PHP中,我们遵循通过按值传递方法将参数传递给函数的方法。我们之所以遵循这种做法,是因为如果函数中参数的值被更改,则在函数外部它不会被更改。 在某些情况下,我们可

    • 问题内容: java中的按引用传递和按引用调用有什么区别? 问题答案: Java不会通过引用传递任何变量。 考虑使用Java中的引用传递对象是很诱人的,但是很有害。对象类型的变量是引用。传递时,它们按值传递。 在其他语言中,按引用传递和按引用调用是同一回事。 编辑: 现有的stackoverflow问题“Java是否通过引用传递?”中提供了更多详细信息。(剧透:没有)

    • 问题内容: 据说在Java方法中,参数是通过值传递的,这对于基元和对象都是正确的,而对象的引用是通过值传递的。为了说明,请考虑以下代码: 能给出相同结果的C ++等价物是什么? 在调用该方法后,使d1的值与该方法内的值相同,即调用方看到修改后的值,那么C ++的等效项是什么? 问题答案: C ++对于值和引用的语义与Java不同。首先,每种类型都有可能通过复制,引用或地址传递(但是,可以通过隐藏复

    • 本文向大家介绍JS是按值传递还是按引用传递,包括了JS是按值传递还是按引用传递的使用技巧和注意事项,需要的朋友参考一下 按值传递 VS. 按引用传递 按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。   按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被

    • 问题内容: 我一直认为Java使用传递引用。 但是,我已经看到了几篇博客文章声称不是(博客文章说Java使用值传递)。 我不认为我能理解他们的区别。 有什么解释? 问题答案: Java总是按值传递。 不幸的是,我们根本不处理任何对象,而是处理称为引用的 对象句柄(当然是通过值传递)。选择的术语和语义很容易使许多初学者感到困惑。 它是这样的: 在上面的示例中仍将返回”Max”。值aDog内main未

    • 问题内容: 我读了许多文章,都说Java是通过价值传递的。但是我仍然不能解释按值传递和引用之间的区别。我写了一个示例程序,它像这样执行。 执行 谁能向我解释这些问题… 价值传递是什么意思? 答:它只是将存储在变量中的数字或值传递给函数。我是对还是错。 How do you say Java是通过价值传递? 为什么Java是按值传递而不是按引用传递? 上面的程序Tries是否显示了“按值传递”和“引