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,
The point of "pass by reference" is to not make a copy as soon as Employee constructor is called, but only when you choose to initialize one of Employee's member with the Date passed.
The main difference between pass by value and pass by reference is that, in a pass by value, the parameter value copies to another variable while, in a pass by reference, the actual parameter passes to the function.
If an argument is significant in size (like a string that's a list), it makes more sense to use pass by reference to avoid having to move the entire string. Effectively, pass by reference will pass just the address of the argument and not the argument itself.
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.
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.)
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:
*
to denote a pointer type; Java's reference (pointers to objects) types don't need an explicit *
.->
to access a field through a pointer; Java just 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.Note that, importantly,
func(something)
, without needing to do anything like taking address or anything.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.
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:
(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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With