16

And who has the authority to decide?

Edit: Apparently I haven't succeeded in formulating my question well.
I am not asking how Java's argument passing works. I know that what looks like a variable holding an object is actually a variable holding a reference to the object, and that reference is passed by value. There are lots of fine explanations of that mechanism here (in the linked threads and others) and elsewhere.

The question is about the technical meaning of the term pass-by-reference. (End edit)

I am not sure if this is the right kind of question for SO, apologies if not, but I don't know a better place. Much has already been said in other questions here, for example Is Java "pass-by-reference" or "pass-by-value"? and pass by reference or pass by value?, but I haven't found an authoritative answer to the question what the term means.

I have thought that "pass by reference" means "pass a reference (usually a pointer) to the object", so the callee can modify the object the caller sees, while "pass by value" means copying the object, and letting the callee have fun with the copy (obvious problem: what if the object contains references, deep copy or shallow).
Sing the FW turns up lots of places saying "pass by reference" means just that, here there's some argument that it means more, but the definition still reads

A ParameterPassing mode where a reference (or if you want to be politically incorrect, a pointer) to the actual parameter is passed into the formal parameter; when the callee needs the formal parameter it dereferences the pointer to get it.

I haven't found many places giving a stronger definition for the term, on this page, I found "The lvalue of the formal parameter is set to the lvalue of the actual parameter." and, if I understand correctly, the same definition is used here ("The formal parameter merely acts as an alias for the actual parameter.")

In fact, the only places I found where the stronger definition is used are places arguing against the notion that in Java, objects are passed by reference (that may be due to my lacking google-fu).

So, if I got things straight, pass-by-reference

class Thing { ... }
void byReference(Thing object){ ... }
Thing something;
byReference(something);

according to the first definition would roughly correspond to (in C)

struct RawThing { ... };
typedef RawThing *Thing;
void byReference(Thing object){
    // do something
}
// ...
struct RawThing whatever = blah();
Thing something = &whatever;
byReference(something); // pass whatever by reference
// we can change the value of what something (the reference to whatever) points to, but not
// where something points to

and in that sense, saying that Java passes objects by reference would be adequate. But according to the second definition, pass-by-reference means more or less

struct RawThing { ... };
typedef RawThing *RawThingPtr;
typedef RawThingPtr *Thing;
void byReference(Thing object){
    // do something
}
// ...
RawThing whatever = blah();
RawThingPtr thing_pointer = &whatever;
byReference(&thing_pointer); // pass whatever by reference
// now we can not only change the pointed-to (referred) value,
// but also where thing_pointer points to

And since Java only lets you have pointers-to-objects (limiting what you can do with them) but doesn't have pointers-to-pointers, in that sense, saying that Java passes objects by reference is totally wrong.

So,

  1. Have I adequately understood the above definitions of pass-by-reference?
  2. Are there other definitions around?
  3. Is there consensus which definition is "the correct one", if so, which?
Community
  • 1
  • 1
Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • 3
    I don't primarily use Java, but I don't think it can pass anything by reference, like VB.NET's `ByRef` or C#'s `ref`. What people actually mean by "pass by reference," I suppose, is "pass a reference type by value." – Ry- Nov 13 '11 at 18:50
  • I think you misinterpret the second example - you actually pass not `whatever` by reference, but `thing_pointer`. – a1ex07 Nov 13 '11 at 18:52
  • 2
    From what I know: Java uses pass-by-value. This means for primitive types the values are copied into the formal parameter. For object references this means: The reference is copied into the formal parameter, thus you get a pass-by-reference behavior – hage Nov 13 '11 at 18:53
  • Perhaps the cleanest way to state it is that "all (class-type) variables are references, and all references are passed by value". Do you know C++? That would allow for a clean answer. – Kerrek SB Nov 13 '11 at 18:53
  • 1
    See this answer: http://stackoverflow.com/questions/7893492/is-java-really-passing-objects-by-value/7893495#7893495 – Eng.Fouad Nov 13 '11 at 18:55
  • @a1ex07 according to the first definition. The second example is meant to give the C correspondence of the second definition. My question is, what is the "official" definition. – Daniel Fischer Nov 13 '11 at 18:59
  • @KerrekSB A bit. You could give it a try. – Daniel Fischer Nov 13 '11 at 19:02
  • I always found that trying to apply ones understanding of C terminology and functioning to java always screwed things up. Java does a number of things that look like one thing but ends up being something else, the pass-by-reference or pass-by-value being one of those things. Just keep in mind that the definition of pass-by-reference goes beyond language terminology, and is essentially just stating that a memory address is passed (or the vm equivalent) to the function. – phill Nov 13 '11 at 19:05
  • @phill So you say definition #1 is the correct one? – Daniel Fischer Nov 13 '11 at 19:21
  • The problem with your second definition is, that an object in Java is the same as `Foo* foo` and NOT `Foo foo`. You pass the pointer to the java object by value, which is not the same as passing the pointer to the java object by reference (which would be `Foo**`). So if you think about a java object `class Foo` as `typedef Foo* FooObj` we're fine, then the C reference examples work fine (and isn't too far from reality if you look at JNI code) – Voo Nov 13 '11 at 19:44
  • @Daniel Fischer the code snippet you use for def #1 is pass-by-reference and is very similar to what ibm shows when they talk about this method of variable passing [link](http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr233.htm). For java, as long as you realize that although it is passing a memory address, it is due to what the object is and not the process undertaken when passing a variable. It appears to be pass-by-reference because the value is a reference but you seem to get that aspect of java. – phill Nov 13 '11 at 20:27

8 Answers8

8

Sure, different people currently have different definitions of what "pass-by-reference" means. And that is why they disagree on whether something is pass-by-reference or not.

However, whatever definition you use, you must use it consistently across languages. You can't say that one language has pass-by-value, and have the exact same semantics in another language and say that it is pass-by-reference. Pointing out the analogies between languages is the best way to address this dispute, because although people might have strong opinions about the passing modes in particular languages, when you contrast the identical semantics with other languages, it sometimes brings counter-intuitive results that force them to re-think their definition.

  • One predominant view is that Java is pass-by-value only. (Search everywhere on the Internet and you will find this point of view.) This view is that objects are not values, but are always manipulated through references, and thus it is references that are assigned or passed, by value. This view holds that the test of pass-by-reference is whether it is possible to assign to a variable in the calling scope.

If one agrees with this viewpoint, then one must also consider most languages, including as diverse ones as Python, Ruby, OCaml, Scheme, Smalltalk, SML, Go, JavaScript, Objective-C, etc. as pass-by-value only. If any of this strikes you as strange or counterintuitive, I challenge you to point out why you think it is different between the semantics of objects in any of those languages from objects in Java. (I know that the some of these languages may explicitly claim that they are pass-by-reference; but it is irrelevant what they say; a consistent definition must be applied to all languages based on the actual behavior.)

  • If you take the opposing view that objects in Java are pass-by-reference, then you must also consider C as pass-by-reference.

Take your Java example:

class Thing { int x; }
void func(Thing object){ object.x = 42; object = null; }
Thing something = null;
something = new Thing();
func(something);

in C, it would be equivalent to this:

typedef struct { int x; } Thing;
void func(Thing *object){ object->x = 42; object = NULL; }
Thing *something = NULL;
something = malloc(sizeof Thing);
memset(something, 0, sizeof(something));
func(something);
// later:
free(something);

I claim that the above are semantically equivalent; only the syntax is different. The only syntax differences are:

  1. C requires an explicit * to denote a pointer type; Java's reference (pointers to objects) types don't need an explicit *.
  2. C uses -> to access a field through a pointer; Java just uses .
  3. Java uses new to dynamically allocate memory for a new object on the heap; C uses malloc to allocate it, and then we need to initialize the memory.
  4. Java has garbage collection

Note that, importantly,

  1. The syntax for calling the function with the object are the same in both cases: func(something), without needing to do anything like taking address or anything.
  2. In both cases, the object is dynamically-allocated (it may live beyond the scope of the function). And
  3. In both cases, the object = null; inside the function does not affect the calling scope.

So the semantics are the same in both cases, so if you call Java pass-by-reference you must call C pass-by-reference too.

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
newacct
  • 119,665
  • 29
  • 163
  • 224
  • I agree with almost all of your answer, especially the statement that most languages are pass-by-value; but I disagree with the statement that Standard ML is pass-by-value *only*. I don't think there's any principled way to distinguish pass-by-value from pass-by-reference semantics as applied to Standard ML: both pass-by-value and pass-by-reference are consistent with the language's semantics, so the only conclusion is that it is *both* pass-by-value *and* pass-by-reference, at the same time. (The same is probably true of OCaml, but I'm less familiar with it, so won't say definitively.) – ruakh Nov 15 '11 at 01:43
  • @ruakh: the way I see it, the ML languages are trivially pass-by-value because it is not possible to assign to a variable. They have mutable data structures, like `ref` and vectors, but so does Java and Python. Again, if everything you can do in SML parameter-passing-wise works the same way in Java or Python, then you must call it the same passing-mode as Java and Python (whether that be pass-by-value or whatever), for consistency – newacct Nov 15 '11 at 10:09
  • 1
    Yes, of course. I agreed that they're pass-by-value; my point is that they are *also* pass-by-reference. (You said that they are pass-by-value *only*.) They have the same passing-mode as pass-by-value languages -- a function receives the value of its argument -- but also the same passing-mode as pass-by-reference languages: a function receives a true alias to its argument. The lack of assignment means that the two modes are equivalent. If a new version of SML were (bizarrely) to have assignment, its creators would have to decide which of those semantics to maintain. – ruakh Nov 15 '11 at 12:50
  • Nice discussion, I had never thought of java's pass-by-semantics that way before. – Matt Fenwick Nov 21 '11 at 23:42
  • @ruakh: Semantically ML is pass-by-value. Different compilers implement parameter passing differently. For instance, a compiler might, instead of passing an object as a parameter, pass _some of its fields_; this is neither pass-by-value nor pass-by-reference. – Heatsink Jul 03 '12 at 23:20
  • @Heatsink: As I've repeatedly said, yes, semantically ML is pass-by-value. It's also semantically pass-by-reference; there is no feature of ML that could distinguish pass-by-value semantics from pass-by-reference semantics. – ruakh Jul 04 '12 at 00:06
  • @ruakh, I thought you were describing how ML is implemented. If you're not trying to describe a language implementation, semantics serves primarily to formalize a language's observable behavior, and unnecessary details are generally left out. Pass-by-reference is more complicated than pass-by-value because it requires to model a readable, writable, addressable memory. By the same token, it would seem strange if you said registers were a part of the semantics. – Heatsink Jul 04 '12 at 00:50
  • @Heatsink: That's a very good point, and when the goal is to describe the semantics of ML, the term "pass-by-reference" is unlikely to be helpful. But when the goal is to explain the difference between pass-by-value and pass-by-reference, I think it's wrong to describe Standard ML as "pass-by-value only". – ruakh Jul 04 '12 at 03:16
  • A major conceptual difference between pass-by-value and pass-by-reference is that in pass-by-value, the recipient is allowed to copy and persist the value that is passed, whereas in pass-by-reference the recipient is *forbidden* from persisting the reference. If one calls `fscanf(myFile,"%d",&myVar);` the variable `myVar` is essentially passed by reference since `fScanf` could not persist a reference to it without invoking Undefined Behavior. By contrast, Java references are promiscuous; there is no way to prevent a routine from persisting them. – supercat May 25 '13 at 04:18
  • I entirely disagree. As an example, take C: `Thing my_thing = {2}; some_func(my_thing);` the *entire* structure `Thing` will be copied onto the stack. I doubt that you are able to come up with any definition of call-by-reference, where this would be interpreted as call-by-reference. C is *call-by-value* for any definition that makes possibly sense. Likewise,it would be call-by-reference, if in my example, instead of copying the value, a reference to `my_struct` would be pushed onto the call stack. Neither C nor Java *implicitly* create references to values when passing them as arguments. – Michael Beer Jun 03 '18 at 21:47
5

Both of your C examples actually demonstrate pass-by-value, because C doesn't have pass-by-reference. It's just that the value that you're passing is a pointer. Pass-by-reference occurs in languages such as Perl:

sub set_to_one($)
{
    $_[0] = 1; # set argument = 1
}
my $a = 0;
set_to_one($a); # equivalent to: $a = 1

Here, the variable $a is actually passed by reference, so the subroutine can modify it. It's not modifying some object that $a is pointing to via indirection; rather, it modifies $a itself.

Java is like C in this respect, except that in Java objects are "reference types", so all you ever have (and all you can ever pass) are pointers to them. Something like this:

void setToOne(Integer i)
{
    i = 1; // set argument = 1
}

void foo()
{
    Integer a = 0;
    setToOne(a); // has no effect
}

won't actually change a; it only reassigns i.

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • a better example would be Pascal, which has both pass-by-value and pass-by-reference. – ninjalj Nov 13 '11 at 19:47
  • Apart from being politically correct there's no difference between `reference of Foo` and `pointer to foo` though - after all that's exactly how it's implemented in c++ and everywhere else.. – Voo Nov 13 '11 at 19:48
  • 1
    @Voo: You're a bit confused. Outside of C++, "a reference to ___" and "a pointer to ___" are roughly equivalent (different languages use slightly variable terminology and slightly variable semantics), but C++ references are completely different from C++ pointers. Obviously they are implemented using pointers (they can be thought of as a thin layer of syntactic sugar), but the resulting semantics are quite different. Unless you think the difference between `while`-loops and `goto`-statements is a matter of "political correctness"? – ruakh Nov 13 '11 at 20:00
  • @ruakh Well there's nothing you can do with `Foo* ptr2Foo` that you can't do with `Foo& ref2Foo` or vice-versa. So thinking about references as a pointer to foo with some trivial syntactic sugar works just fine (except for the handful purists out there). We may assign different semantic value to these things, but when thinking about consequences or limitations you can replace the two and still come to the same result. That doesn't mean I'd replace pointers with references in C++ though. – Voo Nov 13 '11 at 20:35
  • The C snippets were meant to give a rough analogy of what sort of code would be produced for pass-by-reference under each definition. Obviously I made a very bad job of communicating that. – Daniel Fischer Nov 13 '11 at 20:41
  • 2
    @Voo: Since you said "please", I'll point out that `Foo * ptr2Foo = NULL;` is legal, whereas `Foo & ref2Foo = *NULL;` triggers undefined behavior. But really, your comment makes no sense. Yes, you can rewrite code that uses references, and change it to use pointers instead; and yes, that is essentially what a C++ compiler is doing internally; but no, that doesn't mean that "pass-by-reference" and "pass-by-value, with the value being a pointer/reference" are synonymous. The syntax and semantics are both different, both for the function and for its caller. – ruakh Nov 13 '11 at 20:45
  • @DanielFischer: Ah, I see. In that case, I think you're going about this the wrong way. The different calling conventions are a matter of language semantics, not under-the-hood implementation. In theory, I could write a version of a program in a call-by-value language and a version in a call-by-reference language that, with the right compilers, ended up as the exact same same machine code. (Since C++ allows both calling conventions, and its call-by-reference is usually translated pretty trivially into call-by-value-with-pointers, this is not hard to do.) – ruakh Nov 13 '11 at 20:50
  • I rewrote my answer a bit to make it clearer. When thinking about what is allowed and not, you can replace non-leaky abstractions without problems and still arrive at the same limitations/consequences. E.g. instead of thinking of an inner class as well that, you can think of it as a normal class with a reference to its parent and see where you go from there. Sure an implementation detail and only a bit syntactic sugar but it certainly helps understanding why you instantiate an inner class without having a parent.. – Voo Nov 13 '11 at 20:54
  • cont. About your example I agree that that was sloppy - `Foo *const` would work better, although I was talking about what we can do to the object it's pointing to and not the pointer itself. But certainly forgetting the const makes the abstraction leaky in that regard which is exactly what we don't want here. – Voo Nov 13 '11 at 20:56
  • @ruakh "a matter of language semantics" Yes, and my problem is, when people say by reference, which semantics do they mean, the semantics illustrated by the first, or the stronger semantics illustrated by the second? – Daniel Fischer Nov 13 '11 at 21:24
  • @Voo: I agree that it's good to understand (in general terms) how abstractions are implemented; this understanding often explains specific behaviors, such as why real-world C++ compilers *do* generally allow null references, and why Java inner classes can't refer to non-`final` local variables in their containing scope. But if we *only* think of the abstraction in terms of the underlying implementation, then we lose every benefit of the abstraction. – ruakh Nov 13 '11 at 21:26
  • @DanielFischer: Neither. By "language semantics" I'm not talking about objects, but about identifiers. Broadly speaking, there is no C notation that lets two identifiers identify the same object. Assigning to one identifier will never change the other. Both of your C examples are illustrating the same semantics, wherein two different identifiers identify two different pointers (even if both point to the same memory location). That's what "pass-by-value" means. Likewise, in Java, two different identifiers will identify two different references (even if both refer to the same object). – ruakh Nov 13 '11 at 21:38
  • Hmm I intuitively think of inner classes as their "implementation" I think - but I still get all the advantages of the clearer, shorter, simpler syntax, but I see your point - I just wanted to say that for understanding something I often find it extremely helpful to see how it's implemented/could be implemented. @DanielFischer Just think of a java object of `class Foo` as `typedef Foo* FooObj` (`Foo foo` doesn't exist in Java in that form) and always pass that by value - so your first example works. – Voo Nov 13 '11 at 21:41
  • Sigh. Trying to illustrate was a bad idea, muddies far more than it helps. Okay, I have an object, say 64 bytes at memory location 0xF0, and an identifier foo refering to that object. Typically, the compiler would treat foo as four or eight bytes somewhere, 0x00 say, containing the address 0xF0, wouldn't it? So if I call frobnitz(foo); variant 1, frobnitz can change the bytes at 0xF0, but not the 4/8 at 0x00; variant 2, frobnitz can change also the 4/ bytes at 0x00. Def #1 says the object at 0xF0 is passed by reference in variant 1, def #2 says, no, it's only passed by ref. in v2. cont... – Daniel Fischer Nov 13 '11 at 22:32
  • ...cont which implementation-wise would probably mean that what actually gets passed to frobnitz is the adress of the bytes containing the object's address, namely 0x00. If I understand you correctly, you would say that variant 1 is not pass-by-ref? – Daniel Fischer Nov 13 '11 at 22:44
  • @DanielFischer: I would *not* say that variant 1 is not pass-by-ref: I don't have nearly enough information about it. For example, what does `foo = bar;` mean in this hypothetical language? Does it modify the memory at 0x00 to point somewhere other than 0xF0, or does it modify the memory at 0xF0 to match the memory somewhere else? If the language's abstraction is really simply that `foo` identifies the memory at 0xF0, then yes, I would say that variant 1 is pass-by-reference. But that's not the case in Java; in Java, the abstraction is that `foo` identifies a *reference* to an object. – ruakh Nov 13 '11 at 23:52
  • Ah, I think I finally got your point. If you can incorporate that into your answer, I'd be very inclined to accept it. – Daniel Fischer Nov 14 '11 at 00:26
5

Who has the authority to decide? Nobody, and everybody. You decide for yourself; a writer decides for his or her book; and a reader decides whether to agree with the writer.

To understand the term, one needs to go under the hood of the language (and explaining them in terms of C code rather misses the point). Parameter passing styles refer to mechanisms that compilers typically use to create certain behaviour. The following are usually defined:

  • pass by value: the argument is copied into the parameter when the subroutine is entered
  • pass by result: the parameter is undefined when the subroutine is entered, and it is copied to the argument when the subroutine returns
  • pass by value-result: the argument is copied into the parameter at entry, and the parameter is copied into the argument at return
  • pass by reference: a reference to the argument variable is copied to the parameter; any access of the parameter variable is transparently translated into an access of the argument variable

(A note of terminology: a parameter is the variable defined in the subroutine, an argument is the expression that is used in a call.)

Textbooks usually also define pass by name, but it's rare and not easy to explain here. Pass by need also exists.

The importance of the parameter passing style is its effect: in pass by value, any changes made to the parameter is not communicated to the argument; in pass by result, any changes made to the parameter are communicated to the argument at the end; in pass by reference, any changes made to the parameter are communicated to the argument as they are made.

Some languages define more than one passing style, allowing the programmer to select their preferred style for each parameter separately. For example, in Pascal, the default style is pass by value, but a programmer can use the var keyword to specify pass by reference. Some other languages specify one passing style. There are also languages that specify different styles for different types (for example, in C, pass by value is the default but arrays are passed by reference).

Now, in Java, technically we have a language with pass-by-value, with the value of an object variable being a reference to the object. Whether that makes Java pass-by-reference where object variables are concerned is a matter of taste.

ibid
  • 3,891
  • 22
  • 17
  • I would say that in C array arguments get converted to pointers, and that pointer is passed by value. – ninjalj Nov 13 '11 at 19:51
  • Yes, that's how the standard defines it. But the effect is basically the same. – ibid Nov 13 '11 at 19:52
  • The point being that the language is consistent in this, there are no exceptions on how values are passed (though there are exceptions in which expressions cause a conversion from array to pointer, but they are pretty logical exceptions, e.g: `sizeof`) – ninjalj Nov 13 '11 at 19:57
2

Passing by reference is, in effect, passing a reference to a value -- rather than a copy of it -- as an argument.


I guess before we go on, certain things should be defined. I may be using them differently than you're used to seeing them used.

  • An object is a molecule of data. It occupies storage, and may contain other objects, but has its own identity and may be referred to and used as a single unit.

  • A reference is an alias, or handle, to an object. At the language level, a reference mostly acts like the thing it's referring to; depending on the language, the compiler/interpreter/runtime/gnomes will automagically dereference it when the actual object is needed.

  • A value is the result of evaluating an expression. It is a concrete object, that can be stored, passed to functions, etc. (OOP wonks, note i use "object" here in the generic "molecule of data" sense, rather than the OOP "instance of a class" sense.)

  • A variable is a named reference to a pre-allocated value.

    Especially note: variables are not values. The name notwithstanding, variables typically do not change. Their value is what changes. That they're so easily mixed up is partly a testament to how good the reference<-->referent illusion usually is.

  • A reference-typed variable (a la Java, C#, ...) is a variable whose value is a reference.


Most languages, when you pass a variable as an argument, will by default create a copy of the variable's value and pass the copy. The callee binds its name for the parameter to that copy. This is called "passing by value" (or, more clearly, "passing by copy"). The two variables on either side of the call end up with different storage locations, and are thus completely different variables (only related in that they typically start out with equal values).

Passing by reference, on the other hand, doesn't do the copy. Instead, it passes the variable itself (minus the name). That is, it passes a reference to the very same value the variable aliases. (This is typically done by implicitly passing a pointer to the variable's storage, but that's just an implementation detail; the caller and callee don't have to know or care how it happens.) The callee binds its parameter's name to that location. The end result is that both sides use the same storage location (just by possibly different names). Any changes the callee makes to its variable are thus also made to the caller's variable. For example, in the case of object-oriented languages, the variable can be assigned a whole different value.

Most languages (including Java) do not support this natively. Oh, they like to say they do...but that's because people who have never been able to truly pass by reference, often don't grok the subtle difference between doing so and passing a reference by value. Where the confusion comes in with those languages, is with reference-type variables. Java itself never works directly with reference-type objects, but with references to those objects. The difference is in the variables "containing" said objects. The value of a reference-type variable is such a reference (or, sometimes, a special reference value that means "nothing"). When Java passes such a reference, while it doesn't copy the object, it still copies the value (ie: the reference the function gets is a copy of the value the variable refers to). That is, it is passing a reference, but is passing it by value. This allows most of the things that passing by reference allows, but not all.


The most obvious test i can think of for real pass-by-reference support, would be the "swap test". A language that natively supports passing by reference must provide enough support to write a function swap that swaps the values of its arguments. Code equivalent to this:

swap (x, y):       <-- these should be declared as "reference to T"
  temp = x
  x = y
  y = temp

--

value1 = (any valid T)
value2 = (any other valid T)

a = value1
b = value2
swap(a, b)
assert (a == value2 and b == value1)
  1. must be possible and run successfully -- for any type T that permits copying and reassignment -- using the language's assignment and strict equality operators (including any overloads specified by T); and
  2. must not require the caller to convert or "wrap" the args (eg: by explicitly passing a pointer). Requiring that the args be marked as being passed by reference is OK.

(Obviously, languages that don't have mutable variables can't be tested this way -- but that's fine, because they don't matter. The big semantic difference between the two is how modifiable the caller's variable is by the callee. When the variable's value is not modifiable in any case, the difference becomes merely an implementation detail or optimization.)

Note, most of the talk in this answer is about "variables". A number of languages, like C++, also allow passing anonymous values by reference. The mechanism is the same; the value takes up storage, and the reference is an alias to it. It just doesn't necessarily have a name in the caller.

cHao
  • 84,970
  • 20
  • 145
  • 172
  • One major difference between an object reference and a passed-by-reference variable is that languages which support pass-by-reference semantics make it possible to pass references to ephemeral variables, since the recipients of those references will be forbidden from persisting them. Consequently, if `foo` passes `bar` a reference to one of `foo`'s variables, that reference will evaporate as soon as `bar` exits its scope, and since `bar` is guaranteed to exit its scope before `foo` does, that ensures that the reference cannot outlive the variable. By contrast... – supercat Jun 16 '13 at 04:17
  • ...Java does not provide any nice mechanism by which a method `Foo` can pass a reference to `Bar` without having to worry about `Bar` stashing a copy of the reference somewhere. The only thing `Foo` could do would be to construct a wrapper object, pass `Bar` a reference to that wrapper, and then invalidate the wrapper after `Bar` exits. That would be somewhat workable, but highly awkward. – supercat Jun 16 '13 at 04:19
  • Thing is, though doing so recklessly can trigger UB, in C++ you actually *can* semi-easily persist a reference by storing it in a `std::reference_wrapper`...or squirrel away a pointer to the referenced variable. – cHao Jun 16 '13 at 22:02
  • The fact that one can exercise Undefined Behavior in C or C++ without the compiler squawking does not make it legal, nor does it confer upon the compiler or framework any obligation to yield expected behavior. In Java, if one passes a reference to a `Thing` to a method which copies it somewhere, the JVM is required to ensure the object's continued existence as long as any reference exists to it. By contrast, if a C++ method passes a variable to another method by reference, the compiler is under no obligation to ensure that variable will continue to exist once it leaves scope. – supercat Jun 16 '13 at 22:48
  • Different languages and frameworks that support pass-by-reference differ in the lengths to which they'll go to actually prevent methods from improperly persisting references to the passed-in variables, but a common aspect is that any code that uses captured references after they have gone out of scope does so at its own risk. – supercat Jun 16 '13 at 22:51
  • It's not undefined behavior til you try to use the reference after `Foo` returns, though. Even then, if `Foo` got that reference from its caller, it's safe. You're just taking it upon yourself to know more about the lifetime of the referent than the caller provides -- which, yeah, is a bad idea to care about in almost if not all cases. But it's possible, and the behavior is well-defined right up until the referent is destroyed. – cHao Jun 16 '13 at 22:56
  • If the caller is allowed to persist a reference where it may be used at some arbitrary time after it returns, then I'd consider it a reference which is passed by value. If the callee is allowed to pass an ephemeral reference, then I'd consider the target of that reference to be passed by ref. Hybrid designs are possible where a method would sometimes persist passed references, and callers would sometimes pass ephemeral references; such designs need not invoke UB, but are probably best avoided anyway. – supercat Aug 29 '13 at 23:13
1

Java doesn't pass by reference. You are always passing a copy/by value. However if you pass an object then you will get a copy of the reference. So you can directly edit the object, however if you overwrite your local reference then the original object reference won't be overriden.

Udo Held
  • 12,314
  • 11
  • 67
  • 93
1

Wikipedia gives a very clear definition of call-by-reference I can not improve upon:

In call-by-reference evaluation (also referred to as pass-by-reference), a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument- something that will be seen by its caller.

Note that neither of your examples is call-by-reference, because assigning a formal parameter in C never modifies the argument as seen by the caller.

But that's enough copy-pasting, read the thorough discussion (with examples) at

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

meriton
  • 68,356
  • 14
  • 108
  • 175
0

Passing parameters by reference means that the pointer nesting of parameters is deeper than the pointer nesting of local variables. If you have a variable with the type of a class, the variable is a pointer to the actual value. A variable of a primitive type is contains the value itself.

Now, if you pass these variables by value, you keep the pointer nesting: The object reference stays a pointer to the object, and the primitive variable stays the value itself.

Passing the variables as references means that the pointer nesting gets deeper: You pass a pointer to the object reference, so that you can change the object reference; or you pass a pointer to the primitive, so that you can change its value.

These definitions are used in C# and Object Pascal which both have keywords to pass a variable by reference.

To answer your question: Because the last variables - whatever in the first example and thing_pointer in the second one - are passed to the function each through a pointer (&), both are passed by reference.

Yogu
  • 9,165
  • 5
  • 37
  • 58
0

If you are familiar with C, perhaps the following analogy explains how Java works. This will be true only for objects of class-type (and not fundamental type).

In Java, we can have a variable and pass it to a function:

void f(Object x)
{
  x.bar = 5;    // #1j
  x = new Foo;  // #2j
}

void main()
{
  Foo a;
  a.bar = 4;
  f(a);
  // now a.bar == 5
}

In C, this would look as follows:

void f(struct Foo * p)
{
  p->bar = 5;                      // #1c
  p = malloc(sizeof(struct Foo));  // #2c
}

int main()
{
  struct Foo * w = malloc(sizeof(struct Foo));
  w->bar = 4;
  f(w);
  /* now w->bar = 5; */
}

In Java, variables of class-type are always references, which in C would be most faithfully mapped to pointers. But in function calls, the pointer itself is passed by copy. Accessing the pointer as in #1j and #1c modifies the original variable, so in that sense you are passing around a reference to the variable. However, the variable itself is only a pointer, and it itself is passed by copy. So when you assign something else to it. as in #2j and #2c, you are only rebinding the copy of the reference/pointer in the local scope of f. The original variable, a or w in the respective examples, remains untouched.

In short: Everything is a reference, and references are passed by value.

In C, on the other hand, I could implement a true "passing by reference" by declaring void v(struct Foo ** r); and calling f(&w); this would allow me to change w itself from within f.

Note 1: this is not true for fundamental types like int, which are wholly passed by value.

Note 2: A C++ example would be a bit tidier since I could pass the pointer by reference (and I didn't have to say struct): void f(Foo * & r) { r = new Foo; } and f(w);.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • As usual, a fine answer. Unfortunately it's an answer to a question I didn't have. My apologies for wasting your time by being unclear. – Daniel Fischer Nov 13 '11 at 22:51
  • No worries. Is there anything that still needs explaining that isn't covered by the other answers? – Kerrek SB Nov 13 '11 at 22:55
  • That depends on what the answer to point 3. is. If there is consensus (in the sense that a large majority of CS people agree on one meaning, like the overwhelming majority of mathematicians agrees on the meaning of 'prime'), I'd still want to know which meaning. If the answer is, many say so, and many say so, it'd still be nice to have confirmation of that, but that's the impression I got so far. – Daniel Fischer Nov 13 '11 at 23:18
  • Right. I don't know myself if there exists a definitive answer, but it should be fairly clear what the abstract concept means (passing by reference: changing the function argument in the function changes the original object at the call site). *Implementing* by-reference semantics is specific to each language; for instance, in C you can implement it by adding one layer of address-of/pass-a-pointer, while C++ has a native reference type. I guess you should keep the abstract concept and and language-specific implementations separate in your mind. – Kerrek SB Nov 13 '11 at 23:25
  • ... so Java implements "by reference" semantics for objects, but not for variables: since Java does not have a "reference" type modifier, you cannot pass variables (which are always of reference type themselves) by reference again and rebind them through a function call. – Kerrek SB Nov 13 '11 at 23:27