按引用传递与按值传递有什么区别? [英] What's the difference between passing by reference vs. passing by value?

查看:153
本文介绍了按引用传递与按值传递有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么区别

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

请给我一些例子吗?

解决方案

首先,在CS理论中定义的按值传递vs.按引用传递"的区别现在已经过时了,因为最初定义为按引用传递"的技术具有自从失宠后,现在很少使用了. 1

较新的语言 2 倾向于使用不同的(但相似的)技术对来达到相同的效果(请参见下文),这是造成混淆的主要原因. /p>

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

>

现在,真实的定义是:

  • 当参数通过引用传递时,呼叫者和被呼叫者使用相同的变量作为参数.如果被调用方修改了参数变量,则效果对调用方的变量可见.

  • 当参数通过值传递时,调用方和被调用方具有两个独立变量,它们具有相同的值.如果被调用方修改了参数变量,则该效果对调用方不可见.

此定义中要注意的是:

  • 此处的变量"是指调用方的(本地或全局)变量本身-即,如果我通过引用传递局部变量并将其分配给它,则将更改调用方的变量本身,例如无论它指向的是什么指针.

    • 现在认为这是不好的做法(作为隐式依赖).因此,几乎所有较新的语言都是专有的或几乎专有的按值传递.现在,按引用传递主要以输出/输入自变量"的形式用于具有函数功能的语言.不能返回多个值.
  • 通过引用传递"中的引用"的含义.与一般参照"一词的区别在于,此参照"是临时的和隐含的.被呼叫者基本上得到的是与变量某种程度上"相同的变量". 这种效果的具体实现方式是不相关的(例如,该语言可能还公开了一些实现细节-地址,指针,取消引用-都是不相关的;如果最终效果是这样,那就是传递-引用).


现在,在现代语言中,变量趋于属于引用类型" (这是引用传递"之后发明并受其启发的另一种概念),即,实际的对象数据是单独存储的 3

传递此类引用属于传递值,因为从技术上讲变量的值是引用本身,而不是引用的对象.但是,对程序的实际影响可以与按值传递或按引用传递相同:

  • 如果引用只是从调用者的变量中获取并作为参数传递的,则与传递引用具有相同的效果:如果所引用的对象在被调用方中是 mutant ,则调用方会看到变化.
    • 但是,如果重新保存了具有此引用的变量,则它将停止指向该对象,因此对该变量进行的任何进一步操作都会影响它现在指向的内容.
  • 要具有与传递值相同的效果,请在某个时候制作对象的副本.选项包括:
    • 呼叫者可以在呼叫之前制作一个私人副本,然后给被呼叫者一个引用.
    • 在某些语言中,某些对象类型是不可变的":对它们进行的任何似乎更改值的操作实际上都会创建一个全新的对象,而不会影响原始对象.因此,将这样类型的对象作为参数传递始终具有按值传递的效果:如果需要更改,当需要更改时,将自动为被调用方创建一个副本,并且调用方的对象将永远不会受到影响.
      • 在功能语言中,所有对象是不可变的.

如您所见,这对技术与定义中的技术几乎相同,只是间接的程度:只需将变量"替换为引用对象"即可.

没有一个商定的名称,这导致了诸如按值调用,其中值是引用"的错误解释. 1975年,芭芭拉·里斯科夫(Barbara Liskov)提出了"按对象共享呼叫"(或有时只是按共享调用"),尽管它从未流行开来.此外,这些短语都没有与原始短语相似.难怪旧术语最终会在没有更好的结果的情况下被重用,从而导致混乱. 4


注意:很长一段时间以来,这个答案通常是这样说的:

说我想与您分享一个网页.如果我告诉您网址,我就是 通过引用传递.您可以使用该URL查看与我相同的网页 可以看到.如果该页面被更改,我们都会看到更改.如果你 删除网址,您正在做的就是销毁对该网址的引用 页面-您并不是要删除实际的页面本身.

如果我打印出页面并给你打印输出,我正在路过 价值.您的页面是原始文档的断开连接副本.你不会看到 随后进行的任何更改,以及您所做的任何更改(例如,涂写 在您的打印输出上)不会显示在原始页面上.如果你 销毁打印件,您实际上已销毁了 对象-但原始网页保持不变.

这基本上是[em> 正确的 除了引用"的狭义含义-它既是临时的又是隐式的(它不是必须的,但必须是显式的和/或持久性是附加功能,而不是按引用传递"语义的一部分,如上所述).更加贴切的比喻是给您一份文档副本,而不是邀请您处理原始文档.


1 除非您使用Fortran或Visual Basic进行编程,否则它不是默认行为,并且在现代使用的大多数语言中,甚至不可能进行真正的按引用调用. /sub>

2 也有相当多的老年人支持它

3 在几种现代语言中,所有类型都是引用类型.这种方法由1975年的CLU语言首创,此后被包括Python和Ruby在内的许多其他语言所采用.还有许多其他语言使用混合方法,其中一些类型是值类型",而其他类型是引用类型",其中包括C#,Java和JavaScript.

4 回收合适的旧术语本身并没有什么坏处,但必须以某种方式弄清楚每次使用的含义.不这样做正是造成混乱的原因.

What is the difference between

  1. a parameter passed by reference
  2. a parameter passed by value?

Could you give me some examples, please?

解决方案

First and foremost, the "pass by value vs. pass by reference" distinction as defined in the CS theory is now obsolete because the technique originally defined as "pass by reference" has since fallen out of favor and is seldom used now.1

Newer languages2 tend to use a different (but similar) pair of techniques to achieve the same effects (see below) which is the primary source of confusion.

A secondary source of confusion is the fact that in "pass by reference", "reference" has a narrower meaning than the general term "reference" (because the phrase predates it).


Now, the authentic definition is:

  • When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.

  • When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.

Things to note in this definition are:

  • "Variable" here means the caller's (local or global) variable itself -- i.e. if I pass a local variable by reference and assign to it, I'll change the caller's variable itself, not e.g. whatever it is pointing to if it's a pointer.

    • This is now considered bad practice (as an implicit dependency). As such, virtually all newer languages are exclusively, or almost exclusively pass-by-value. Pass-by-reference is now chiefly used in the form of "output/inout arguments" in languages where a function cannot return more than one value.
  • The meaning of "reference" in "pass by reference". The difference with the general "reference" term is is that this "reference" is temporary and implicit. What the callee basically gets is a "variable" that is somehow "the same" as the original one. How specifically this effect is achieved is irrelevant (e.g. the language may also expose some implementation details -- addresses, pointers, dereferencing -- this is all irrelevant; if the net effect is this, it's pass-by-reference).


Now, in modern languages, variables tend to be of "reference types" (another concept invented later than "pass by reference" and inspired by it), i.e. the actual object data is stored separately somewhere (usually, on the heap), and only "references" to it are ever held in variables and passed as parameters.3

Passing such a reference falls under pass-by-value because a variable's value is technically the reference itself, not the referred object. However, the net effect on the program can be the same as either pass-by-value or pass-by-reference:

  • If a reference is just taken from a caller's variable and passed as an argument, this has the same effect as pass-by-reference: if the referred object is mutated in the callee, the caller will see the change.
    • However, if a variable holding this reference is reassiged, it will stop pointing to that object, so any further operations on this variable will instead affect whatever it is pointing to now.
  • To have the same effect as pass-by-value, a copy of the object is made at some point. Options include:
    • The caller can just make a private copy before the call and give the callee a reference to that instead.
    • In some languages, some object types are "immutable": any operation on them that seems to alter the value actually creates a completely new object without affecting the original one. So, passing an object of such a type as an argument always has the effect of pass-by-value: a copy for the callee will be made automatically if and when it needs a change, and the caller's object will never be affected.
      • In functional languages, all objects are immutable.

As you may see, this pair of techniques is almost the same as those in the definition, only with a level of indirection: just replace "variable" with "referenced object".

There's no agreed-upon name for them, which leads to contorted explanations like "call by value where the value is a reference". In 1975, Barbara Liskov suggested the term "call-by-object-sharing" (or sometimes just "call-by-sharing") though it never quite caught on. Moreover, neither of these phrases draws a parallel with the original pair. No wonder the old terms ended up being reused in the absense of anything better, leading to confusion.4


NOTE: For a long time, this answer used to say:

Say I want to share a web page with you. If I tell you the URL, I'm passing by reference. You can use that URL to see the same web page I can see. If that page is changed, we both see the changes. If you delete the URL, all you're doing is destroying your reference to that page - you're not deleting the actual page itself.

If I print out the page and give you the printout, I'm passing by value. Your page is a disconnected copy of the original. You won't see any subsequent changes, and any changes that you make (e.g. scribbling on your printout) will not show up on the original page. If you destroy the printout, you have actually destroyed your copy of the object - but the original web page remains intact.

This is mostly correct except the narrower meaning of "reference" -- it being both temporary and implicit (it doesn't have to, but being explicit and/or persistent are additional features, not a part of the pass-by-reference semantic, as explained above). A closer analogy would be giving you a copy of a document vs inviting you to work on the original.


1Unless you are programming in Fortran or Visual Basic, it's not the default behavior, and in most languages in modern use, true call-by-reference is not even possible.

2A fair amount of older ones support it, too

3In several modern languages, all types are reference types. This approach was pioneered by the language CLU in 1975 and has since been adopted by many other languages, including Python and Ruby. And many more languages use a hybrid approach, where some types are "value types" and others are "reference types" -- among them are C#, Java, and JavaScript.

4There's nothing bad with recycling a fitting old term per se, but one has to somehow make it clear which meaning is used each time. Not doing that is exactly what keeps causing confusion.

这篇关于按引用传递与按值传递有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆