2013-09-17 3 views
2

Я просто прочитать следующую статью о том, какой передаче по ссылке и передачи по значению означает: http://qntm.org/callPython, Java, C: Передавать по ссылке или Проходит Value Differences

Так просто чтобы убедиться, что я правильно понять. .. Означает ли это, что вызов по значению в функциях НЕ изменяет исходные входы, а только локальную копию этого ввода? Однако, поскольку в Java и Python значения фактически являются ссылками на значения, означает ли это, что вызов по значению в функциях изменит исходные входы?

+9

Изменяя локальную переменную ссылку не изменит тот, который вы передаёте в Изменение объекта с помощью доступа к нему через ссылку изменит. объект. –

+0

Что именно вы подразумеваете под вход? –

+0

Введите как переменные, которые вы передадите в функцию. Извините, если мой словарь свободен, я над этим работаю! –

ответ

3

Это зависит от того, что именно вы имеете в виду путем ввода, значит, специально ли переменная, которая появляется в качестве аргумента на месте вызова, например, x в:

Object x = ...; 
someMethod(x); 

или вы говорите о реальном объекте что вызываемая функция будет видеть, например, фактический экземпляр объекта в:

someMethod(new Object()); 

значение переменных (то есть, какой объект они ссылаются) не изменится, но вы можете сделать что-то в объекты tha вы получите. Например,

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

Я думаю, что это лучший способ объяснить этот нюанс. +1. – nook

+0

@ publ1c_stat1c Это интересный нюанс, потому что если вы работаете на языке (например, Java), где вы не можете изменить значение переменной, сделав вызов метода с переменной в качестве аргумента в источнике (например, 'someMethod (x)'), тогда может быть трудно представить, почему любой язык будет делать это. Но на некоторых языках вы можете. :) –

1

В Java существует несколько основных типов переменных: int, long, float, double и reference. Ссылки - это то, что вы обычно называете объектами, например String. Однако то, что фактически хранится в ссылочной переменной, - это не сам объект, а скорее адрес, в котором фактический объект находится в памяти.

Вы никогда не видите это на Java, если вы пишете String str = "hello", вы думаете о str как строка «привет». Но на самом деле, str содержит номер - адрес памяти - там, где хранится фактическая строка «привет».

Когда вы вызываете метод в 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" 
} 
Смежные вопросы