两者有什么区别
引用传递的参数 参数通过value?
你能给我举几个例子吗?
两者有什么区别
引用传递的参数 参数通过value?
你能给我举几个例子吗?
当前回答
问题是“vs”。
没有人指出一个重要的点。在传递值时,会占用额外的内存来存储传递的变量值。
在传递引用时,值不会占用额外的内存(在某些情况下内存是有效的)。
其他回答
首先,CS理论中定义的“通过值传递与通过引用传递”的区别现在已经过时了,因为最初定义为“通过引用传递”的技术已经不再受欢迎,现在很少使用
较新的语言2倾向于使用不同(但相似)的技术来实现相同的效果(见下文),这是混淆的主要来源。
第二个混淆的来源是,在“通过引用传递”中,“引用”的含义比一般术语“引用”更窄(因为这个短语比它更早)。
真实的定义是:
通过引用传递参数时,调用方和被调用方对参数使用相同的变量。如果被调用方修改了参数变量,则对调用方的变量可见。 当参数按值传递时,调用方和被调用方有两个具有相同值的自变量。如果被调用方修改了参数变量,则对调用方不可见。
在这个定义中需要注意的是:
"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 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).
现在,在现代语言中,变量倾向于“引用类型”(另一个比“按引用传递”更晚发明的概念,并受到它的启发),即实际的对象数据被单独存储在某个地方(通常是在堆上),只有对它的“引用”被保存在变量中并作为参数传递
传递这样的引用属于值传递,因为从技术上讲,变量的值是引用本身,而不是被引用的对象。然而,对程序的最终影响可以是值传递或引用传递:
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 reassigned, 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.
正如你可能看到的,这对技术几乎与定义中的技术相同,只是在某种程度上间接地:只需将“变量”替换为“引用对象”。
它们没有统一的名称,这导致了一些扭曲的解释,比如“按值调用,其中值是引用”。1975年,Barbara Liskov提出了“按对象调用共享”(有时简称为“按对象调用共享”)这个术语,尽管它从未流行起来。此外,这两个短语都不能与原来的短语相提并论。难怪在没有更好的东西的情况下,旧的术语最终被重新使用,导致混乱
(对于新技术,我会使用术语“新的”或“间接的”值传递/引用传递。)
注:很长一段时间以来,这个答案都是这样说的:
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.
这在很大程度上是正确的,除了狭义意义上的“引用”——它既是临时的又是隐式的(它不一定必须是临时的,但显式和/或持久性是额外的特性,不是引用传递语义的一部分,如上所述)。一个更接近的类比是给你一份文件的副本,而不是邀请你处理原件。
除非你用Fortran或Visual Basic编程,否则它不是默认行为,在现代使用的大多数语言中,真正的引用调用甚至是不可能的。
相当多的老年人也支持这一点
在一些现代语言中,所有类型都是引用类型。这种方法是由CLU语言在1975年首创的,后来被许多其他语言采用,包括Python和Ruby。还有更多的语言使用混合方法,其中一些类型是“值类型”,另一些是“引用类型”——其中包括c#、Java和JavaScript。
重复使用一个合适的旧术语本身并没有什么不好,但人们必须弄清楚每次使用的是什么意思。不这么做正是造成混乱的原因。
It's a way how to pass arguments to functions. Passing by reference means the called functions' parameter will be the same as the callers' passed argument (not the value, but the identity - the variable itself). Pass by value means the called functions' parameter will be a copy of the callers' passed argument. The value will be the same, but the identity - the variable - is different. Thus changes to a parameter done by the called function in one case changes the argument passed and in the other case just changes the value of the parameter in the called function (which is only a copy). In a quick hurry:
Java only supports pass by value. Always copies arguments, even though when copying a reference to an object, the parameter in the called function will point to the same object and changes to that object will be see in the caller. Since this can be confusing, here is what Jon Skeet has to say about this. C# supports pass by value and pass by reference (keyword ref used at caller and called function). Jon Skeet also has a nice explanation of this here. C++ supports pass by value and pass by reference (reference parameter type used at called function). You will find an explanation of this below.
代码
因为我的语言是c++,我将在这里使用它
// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
p = NULL;
}
// passes an integer
void call_by_value(int p) { // :2
p = 42;
}
// passes an integer by reference
void call_by_reference(int & p) { // :3
p = 42;
}
// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
*p = 10; // changes what p points to ("what p references" in java)
// only changes the value of the parameter, but *not* of
// the argument passed by the caller. thus it's pass-by-value:
p = NULL;
}
int main() {
int value = 10;
int * pointer = &value;
call_by_value(pointer); // :1
assert(pointer == &value); // pointer was copied
call_by_value(value); // :2
assert(value == 10); // value was copied
call_by_reference(value); // :3
assert(value == 42); // value was passed by reference
call_by_value_special(pointer); // :4
// pointer was copied but what pointer references was changed.
assert(value == 10 && pointer == &value);
}
Java中的一个例子不会有什么坏处:
class Example {
int value = 0;
// similar to :4 case in the c++ example
static void accept_reference(Example e) { // :1
e.value++; // will change the referenced object
e = null; // will only change the parameter
}
// similar to the :2 case in the c++ example
static void accept_primitive(int v) { // :2
v++; // will only change the parameter
}
public static void main(String... args) {
int value = 0;
Example ref = new Example(); // reference
// note what we pass is the reference, not the object. we can't
// pass objects. The reference is copied (pass-by-value).
accept_reference(ref); // :1
assert ref != null && ref.value == 1;
// the primitive int variable is copied
accept_primitive(value); // :2
assert value == 0;
}
}
维基百科
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
这家伙说得很准:
http://javadude.com/articles/passbyvalue.htm
在理解这两个术语之前,您必须了解以下内容。每一个物体都有两个可以使它被区分的东西。
它的价值。 它的地址。
如果你说employee。name = "John",要知道关于name有两件事。它的值是“John”,它在内存中的位置是一个十六进制数,可能像这样:0x7fd5d258dd00。
根据语言的体系结构或对象的类型(类、结构等),可以传输“John”或0x7fd5d258dd00
传递“John”称为按值传递。
传递0x7fd5d258dd00称为引用传递。任何指向这个内存位置的人都可以访问“John”的值。
有关这方面的更多信息,我建议您阅读有关取消指针引用的内容,以及为什么选择struct(值类型)而不是类(引用类型)。
“按值传递”将发送存储在指定变量中的数据的副本,“按引用传递”将发送到变量本身的直接链接。
因此,如果你通过引用传递一个变量,然后改变你传递给它的块中的变量,原始变量将被改变。如果只是按值传递,原始变量将不能被传递到的块所改变,但您将获得调用时它所包含的任何内容的副本。
看看这张照片:
在第一种情况下(通过引用传递),当变量在函数内部设置或更改时,外部变量也会更改。
但在第二种情况下(按值传递),改变函数内部的变量不会对外部变量产生任何影响。
要阅读这篇文章,请参见这个链接。