Python,Java,C:通过引用传递或通过值差异传递

时间:2013-09-17 18:17:07

标签: java python c

我刚刚阅读了以下关于通过引用传递和传递值的文章:http://qntm.org/call

所以只是为了确保我正确理解......这是否意味着在函数中按值调用不会改变原始输入,只会改变该输入的本地副本?但是,因为在Java和Python中,值实际上是对值的引用,这是否意味着在函数中按值调用会改变原始输入吗?

2 个答案:

答案 0 :(得分:5)

这取决于输入的确切含义,具体来说,您是指在调用网站上显示为参数的变量,例如: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').
}

但是,更新方法中的引用不会更改方法之外的任何引用。在方法中,您不能通过分配方法的其中一个参数来更改方法外部变量引用的对象。 E.g:

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.
}

答案 1 :(得分:1)

在Java中,有一些基本类型的变量:int,long,float,double和references。 引用是您通常称为对象的引用,例如String。但是,实际存储在引用变量中的不是对象本身,而是实际对象在内存中的位置。

你永远不会在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"
}