Чим відрізняється передача за посиланням від передачі за значенням?

У чому різниця між

  1. параметром, що передається за посиланням
  2. параметром, що передається за значенням?

Наведіть, будь ласка, кілька прикладів.

Це спосіб передачі аргументів у функції. Передача за посиланням означає, що параметр викликаної функції буде таким самим, як і переданий аргумент викликаючої функції (не значення, а саме ідентичність - сама змінна). Передача за значенням означає, що параметр функції, що викликається, буде копією переданого аргументу. Значення буде те саме, але ідентифікатор - змінна - інша. Таким чином, зміни параметру, що виконуються викликаною функцією, в одному випадку змінюють переданий аргумент, а в іншому випадку просто змінюють значення параметру у викликаній функції (яка є лише копією). На швидку руку:

  • Java підтримує тільки передачу за значенням. Завжди копіює аргументи, навіть якщо при копіюванні посилання на об'єкт, параметр у викликаній функції буде вказувати на той самий об'єкт і зміни в цьому об'єкті буде видно у викликаючій функції. Оскільки це може збити з пантелику, тут про це говорить Джон Скіт (Jon Skeet).
  • C# підтримує передачу за значенням та передачу за посиланням (ключове слово ref використовується у викликаючій та викликаній функції). Джон Скіт також має гарне пояснення з цього приводу тут.
  • Мова C++ підтримує передачу за значенням та передачу за посиланням (тип параметру посилання, що використовується у викликаючій функції). Нижче наведено пояснення щодо цього.

Коди

Оскільки моя мова програмування 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

Коментарі (5)

Наведу приклад:


#include 

void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }

int main()
{
    int x = 0;
    by_val(x); std::cout 
Коментарі (5)

При передачі за посиланням передається фактично покажчик на змінну. При передачі за значенням ви передаєте копію змінної. У базовому використанні це зазвичай означає, що при передачі за посиланням зміни у змінній будуть помічені викликаючим методом, а при передачі за значенням вони не будуть помічені.

Коментарі (0)