Ah. That clears some things up. A trailing const only makes sense in
terms of pointers, not references.
So, say you had a block of code that looked like this:
vector<int> values;
init(values);
void init(vector<int> & values)
{
vector<int> v;
values = v; // assignment operator
}
How can I tell the compiler a) that I don't want to change the vector
and b) that I don't want the vector to be reassigned?
My guess right now is you handle both a and b the same way, since the
assignment operator modifies the internals of the vector.
Working in languages like C# and Java, where everything is a reference
type, it is strange to think that an assignment modifies the contents
of the original vector (copying v), rather than simply refering both
to the same vector.
On the other hand, pointers work the same way as reference types in
Java and C#, hence the ability to add the extra const onto the end.
Let me know if I'm on the right trail.
Sort of. Unfortunately, AFAIK, Java developers decided that "pointer"
was a dirty word and used the word "reference" instead. Java
references really ought to have been called pointers. Java references
have more or less the same semantics as C++ pointers (except of course
no pointer arithmetic, etc.). That is, a C++ pointer is a "region of
memory" distinct from the "region of memory" of the pointed-to thingy.
Same as Java. In C++ parlance, the pointer is an object, and it points
to a separate object.
int x; // an object
int* y = & x; // the pointer object y points to the int object x
A C++ reference is not a distinct object. It is merely another name
for a pre-existing object. Now, as an implementation detail, it's
probably implemented as a pointer, but that's an implementation
detail. You cannot make a const reference (contrast with "reference to
const"). All references are implicitly "const" - all references are
unchangeable. You cannot "reseat" a reference. Once a C++ reference is
created, it "points" to the same object for the reference's lifetime.
Any attempt to reseat the reference invokes undefined behavior (more
or less - IIRC there might be an obscure exception or two - ignore
that for now).
So, for:
void foo(vector<int> * x)
The body of the function can reassign x to point to a different vector
object. The caller's pointer remains unchanged no matter what.
However, the pointed-to object may be changed, and this is visible to
the caller. That is, pointer have "pass by value" semantics, just like
Java references. A change to the C++ pointer object in the body does
not affect the caller, but a change to the pointed-to object does
affect the caller.
void foo(vector<int> & x)
The body of the function cannot reassign x to "point" to a different
vector object. Any attempt to do so is undefined behavior (more or
less - IIRC there might be an obscure exception or two - ignore that
for now). "x" is just another name for an already existing vector
object. Any changes to x will affect the caller.
void foo(vector<int> const * x)
The caller knows that the function body won't modify the vector object
(more or less - const_casts can, and you might be able to obtain a non-
const reference to it through some other means and modify it through
that).
void foo(vector<int> * const x)
The caller doesn't care about this const. This const only affects the
body's local pointer object which the caller does not see.
void foo(vector<int> const & x)
The caller knows that the function body won't modify the vector object
(more or less - const_casts can, and you might be able to obtain a non-
const reference to it through some other means and modify it through
that).
void foo(vector<int> & const x)
Ill-formed code. References are not distinct objects from the "pointed
to" object. They are simply another name for an existing object. The
const there doesn't mean anything.