> Maybe that shouldn't even be exposed to the programmer. The programmer-level questions are, is it copyable, is it mutable, and is it alias-free? Whether it's passed as a copy or a pointer is really an issue for the compiler.
The problem here is the definition of "call by reference". In C++ that means being able to change the value outside of the function taking the reference.
void setByReference(float& v) { v = 123; }
float v;
setByReference(v);
cout << v; // prints 123
That feature of being able to pass by reference doesn't exist in say, JavaScript. you can only pass by value in JavaScript. The types of values in JS are undefined, null, boolean, number, string, reference-to-function, reference-to-object. You can never pass anything by reference, only by value.
And that's where it gets confusing. If you have a variable who's value is a reference-to-object you pass the value. The value being "reference-to-object"
To re-iterate
const n = 1; fn(n); // call by value, type of value = number
const s = 'abc' fn(s); // call by value, type of value = string
const o = {} fn(o); // call by value, type of value = reference-to-object
In C++ though, you pass the a reference to the variable itself (in the example above). That's called call-by-reference.
Yeah, this is one of those things that while it may be more technically correct causes a lot of unnecessary confusion. I remember being confused by this as a C++ programmer learning Java when resources claimed that Java was always pass by value where the actual behaviour in almost all cases (due to Java going almost all-in on objects) is what a C++ programmer would expect from pass by reference.
I still see even relatively experienced programmers who don't understand this, particularly working with Unity where a lot of programmers came from C++ to C# and don't realise for example that a C# function that takes a List 'by value' and modifies it is actually modifying the same instance that was passed in by the caller.
No, Java really is pass by value. You can rely on this in Java:
String s = "hello";
foo(s);
assert s == "hello";
In C++, if the function takes a non-const reference, you can't.
Yes, Java always passes pointers to objects. But you can pass pointers by value. And passing a pointer by value is not the same as passing by reference!
I think the origin of the confusion around a function taking a list by value and the like is the implicitness of pointers in Java and its cousins. This Java method:
void foo(List<String> strings)
Is the equivalent of this C++ method:
void foo(shared_ptr<List<string>> strings)
True systems languages make the pointers explicit.
That's only because strings are immutable in Java. It's not true for reference types in general.
In C++ passing a pointer by value is effectively the same as passing a reference, the only real difference being that the syntax for accessing the underlying value is more implicit for a reference.
No, in Java, this is true for reference types in general. The method receiving the pointer can mutate the object, but it can't change which object the original variable points to.
This is also true when passing a pointer variable by value in C or C++. It is not true when passing a reference in C++ - the receiving method can change which object the original variable points to.
Ok, that's not really what your example showed though. You seem to be relying on string interning to have two different "hello" literals refer to the same underlying object and therefore be equal? Coming from other languages, and specifically C++, I tend to see `==` as value rather than reference equality so that wasn't immediately obvious to me.
The equivalent code in C++ has different semantics but a function that takes a non const reference in C++ cannot change what the reference refers to (references are immutable in that sense in C++, they can only ever refer to one object). What a non const reference allows in C++ is for the called function to change the value of the object referred to and since strings are not immutable in C++ that means that the value of string s could change, not the object identity.
With pointers to pointers, or references to pointers in C++ you can further change the object pointed to / referred to but not with references (there's no such thing as a reference to a reference in C++).
The problem here is the definition of "call by reference". In C++ that means being able to change the value outside of the function taking the reference.
That feature of being able to pass by reference doesn't exist in say, JavaScript. you can only pass by value in JavaScript. The types of values in JS are undefined, null, boolean, number, string, reference-to-function, reference-to-object. You can never pass anything by reference, only by value.And that's where it gets confusing. If you have a variable who's value is a reference-to-object you pass the value. The value being "reference-to-object"
To re-iterate
In C++ though, you pass the a reference to the variable itself (in the example above). That's called call-by-reference.I can see why the OP feels it's muddled.