The * is not dereference. It indicates a pointer.
* means both - in variable declarations it indicates a pointer type, in expressions it means dereference (a pointer).
Parameters are passed by reference, not received be reference.
That doesn't make sense - the receiver (the 'callee') has to know how the caller passed the variable, so if it is passed by reference then it must be received as a reference. If caller and callee disagree on the calling protocol then the result could be nonsense!
The '&' operator means 'address of', the & type operator means 'pass by reference'. The '*' type operator means 'pass by value', but that the value will be a reference (a pointer). The distinction can be confusing to newcomers of course - but the rule is if you use '&' (pass by reference) then the compiler knows to automatically dereference appropriately. If you pass a pointer then the compiler leaves that task to you to get right. The type system means that you will get warnings or errors if you get confused.
void foo (int & x)
x++ ; // increment the variable that is passed by reference - x is an alias for the actual variable in the call.
void bar (int y)
y++ ; // increment the local variable y - this has no effect on any other variable. (this example has no useful effect at all!)
void baz (int * z)
(*z)++ ; // increment the value in the address held in the (pass-by-value) variable z
void main ()
int a = 0 ;
bar (a) ; // pass a's value, no change to a
foo (a) ; // pass a by reference, a is incremented
baz (&a) ; // pass a's address by value, a is incremented.
bar (7) ; // legal, nothing useful results(!)
foo (7) ; // not legal - the parameter must be a variable
baz (7) ; // not legal, a type mismatch
baz ((int *) 7) ; // typecast makes this legal, but unless you know what is at address 7, this is nonsense code.
Note that foo
will typically be compiled to exactly the same object code...