我刚刚阅读了以下关于引用传递和值传递意味着什么的文章:http: //qntm.org/call
所以只是为了确保我理解正确......这是否意味着在函数中按值调用不会改变原始输入,只会改变该输入的本地副本?但是,由于在 Java 和 Python 中,值实际上是对值的引用,这是否意味着在函数中按值调用会改变原始输入?
我刚刚阅读了以下关于引用传递和值传递意味着什么的文章:http: //qntm.org/call
所以只是为了确保我理解正确......这是否意味着在函数中按值调用不会改变原始输入,只会改变该输入的本地副本?但是,由于在 Java 和 Python 中,值实际上是对值的引用,这是否意味着在函数中按值调用会改变原始输入?
这取决于您输入的确切含义,特别是您是否指在调用站点作为参数出现的变量,例如x
:
Object x = ...;
someMethod( x );
或者您正在谈论被调用函数将看到的实际对象,例如,实际的 Object 实例:
someMethod( new Object() );
变量的值(即它们所指的对象)不会改变,但是你仍然可以对你得到的对象做一些事情。例如,
void appendX( StringBuilder sb ) {
sb.append('x');
}
void foo() {
StringBuilder builder = ...
appendX( builder );
builder.toString(); // will contain 'x' because you worked with the object that
// is the value of the variable `builder`. When appendX was
// was invoked, the value of its variable `sb` was the same
// object that is the value of foo's `builder`. Without
// changing what value the variable `builder` refers to, we
// did "change" the object (i.e., we appended 'x').
}
但是,更新方法中的引用不会更改方法之外的任何引用。在方法内,您不能通过分配给方法的一个参数来更改方法外的变量所引用的对象。例如:
void setNull( StringBuilder sb ) {
sb = null;
}
void foo() {
StringBuilder builder = ...
appendX( builder );
builder == null; // false, because the value of the variable `builder` is still the
// same object that it was before. Setting variable `sb` in setNull
// to null doesn't affect the variable `builder`. The variables are
// just a name so that you can refer to an value. The only way to
// what value a variable refers to is with an assignment.
}
在 Java 中,有几种基本类型的变量:int、long、float、double 和引用。引用是您通常所说的对象,例如字符串。但是,实际存储在引用变量中的不是对象本身,而是实际对象在内存中的地址。
在 Java 中你永远不会看到这个,如果你写String str = "hello"
,你会认为是str
字符串“hello”。但实际上,str
它包含一个数字 - 一个内存地址 - 实际字符串“hello”的存储位置。
在 Java 中调用方法时,会复制其参数(按值传递)。即使对于像字符串这样的对象也是如此——除了实际对象没有被复制,只是引用。但是,由于引用指向未复制的某些内容(内存中的实际对象位置),您可以使用引用来修改实际对象,即使在函数之外。
在 C 中,您实际上可以使用指针通过引用传递:
void changeA(int* a) {
*a = 5
}
int main(void) {
a = 10;
changeA(&a); // pass by reference - &a means "address of a", similar to a reference in java
printf("a: %d\n", a); // prints "5"
}