I've just started learning C++ a few days ago (coming from a C# background) and am going through the headache at the moment of getting to grips with pointers and references etc. (No, I've never used pointers in C# and I'm only using them now because it seems polymorphism depends on them in C++, joy.) I think I've worked it all out in my head now after reading some existing literature around SO and Wikipedia etc but I want to check if I've got it right here. Please correct me if anything below is incorrect.
I gather when applied as a prefix &
gets the address of a variable, whereas *
dereferences it (if the variable is a pointer). Dereferencing a variable which is not a pointer is illegal, thus the operators define transitions up and down a ladder of 'pointerness' starting at the raw object level and continuing indefinitely in the &
direction. In this sense the operators are inverses in this context.
Now, I also see that when declaring variables we can equivalently write
int *newVariable;
and
int* newVariable;
and similarly with &
(and indeed with any spacing around the *
as it can equivalently resolve to either case).
The former is interpreted as the *
operating on the variable as before:
"Declare a variable 'newVariable' such that when it's dereferenced, it points to an int
". This makes it an int
pointer.
The latter is instead interpreted as the *
operating on the type int
, the meaning of which is defined as T*
being a pointer to T
: "Declare a variable 'newVariable' which is a pointer to an int
".
This is suggestive that the same relations we have for them acting on a variable extend to when they act on a type. This has caused some confusion for me as it seems that unlike *
, &
is inconsistent and changes its behaviour here such that the former interpretation of the declaration above does not hold for &
as well as *
.
In this context, ie. operating on a type or on a variable in its declaration, it no longer appears to have the same meaning, and thus ceases to be an inverse operation to *
. Here, &
declares a variable as a reference to the type, which is orthogonal to the 'pointerness' ladder. You can have a reference to any type on the ladder, but you cannot have a pointer to a reference and you cannot have a reference to a reference. Thus the operator combination in a declaration must be a (possibly empty) string of *
s possibly followed by a &
.
The syntax for assigning a reference is the same as that for a raw object - if assigned to another reference then it is directed to point at the object the other reference points to. Also, a reference cannot be dereferenced with *
- rather, every interaction with the reference is automatically dereferenced by the compiler so you can act on it as if it were the object itself.
Additionally, when passing variables through function arguments, the raw object is always shallow copied in memory to the new variable in the function scope if it's not a reference (in the case of a pointer, this just means an address is copied). If it is a reference, then the function just receives a new reference object pointing to the same thing as the reference it took in, so this works in much the same way as value types and reference types in .Net.
Does all of this sound roughly right?
Thanks! (I know this isn't exactly the first question on the topic...)