What's the difference between passing by reference vs. passing by value?

What is the difference between

  • a parameter passed by reference
  • a parameter passed by value?
  • Could you give me some examples, please?


    When a parameter is passed by reference , the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.

    When a parameter is passed by value , the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.

    However , if the value in question is a mutable reference-type object or otherwise indirectly references other values, then you can emulate call-by-reference in a call-by-value environment: if the callee modifies the object (or other values pointed to by the object), those modifications are visible to the caller. But the emulation isn't exactly the same, since only modifications to the object, not to the variable, are visible. This leads to contorted explanations like "call by value where the value is a reference". This somewhat confusing state of affairs is how many popular programming languages work today, and therefore people often confuse passing mutable objects by value with call-by-reference.

    For more explanation, see the other answers below.


    NOTE : For a long time, this answer used to say:

    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 (eg 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.

    It's a simple analogy that's easy to understand, which got this post hundreds of upvotes. However, the analogy is flawed: call-by-reference and call-by-value are not like URLs. (A reference type in a language like C# is like a URL; see Jon Skeet's great write-up about reference types in .NET for details. But reference types are not the same thing as pass by reference.)

    Since this analogy is not actually correct, it's been removed from this answer. See also the comments below where this was discussed.


    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.
  • Codes

    Since my language is C++, i will use that here

    // 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);
    }
    

    And an example in Java won't hurt:

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

    Wikipedia

    http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value

    http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference

    This guy pretty much nails it:

    http://javadude.com/articles/passbyvalue.htm


    这里是一个例子:

    #include <iostream>
    
    void by_val(int arg) { arg += 2; }
    void by_ref(int&arg) { arg += 2; }
    
    int main()
    {
        int x = 0;
        by_val(x); std::cout << x << std::endl;  // prints 0
        by_ref(x); std::cout << x << std::endl;  // prints 2
    
        int y = 0;
        by_ref(y); std::cout << y << std::endl;  // prints 2
        by_val(y); std::cout << y << std::endl;  // prints 2
    }
    
    链接地址: http://www.djcxy.com/p/456.html

    上一篇: 通过引用传递或通过值传递?

    下一篇: 传递引用与价值传递之间有什么区别?