Before saying it would be a duplicate question and downvote (as it happened before), I searched and found nothing alike.
I, like many others, am trying to learn the uses of C++ reference variables and to relate them to pointers. I found it easier to make a table and I need to know whether it needs to be amended.
int *n int n int &n caller/local
void foo(int *n) n &n &n caller
void foo(int n) *n n n local
void foo(int &n) *n n n caller
The table wants to reflect all legal passed parameters.
[1,1]: passing by reference (trivial)
[1,2]: passing by reference
[1,3(1)]: passing by reference, an is an address(?)
[1,3(2)]: passing by reference, as n is used as alias(?)
[2,1]: passing by value, as dereferencing
[2,2]: passing by value (trivial)
[2,3(1)]: passing by value, using value of n (where n is an alias)
[2,3(2)]: passing by value (dereferencing n, which is an address)
[3,1(1)]: passing by reference, as foo accepts address
[3,1(2)]: passing by reference, reference of value at address n
[3,2(1)]: passing by reference (trivial)
[3,2(2)]: passing by reference, as foo accepts address or reference
[3,3]: passing by reference (trivial, as argument matches parameter exactly)
A function
void foo(int& n);
does not accept an address (a pointer), and not literals either.
So you can't call it like
int a = ...;
foo(&a); // Trying to pass a pointer to a function not taking a pointer
or
foo(1); // Passing R-value is not allowed, you can't have a reference to a literal value
There is an exception though, if you have a constant reference, like
int foo(const int& n);
then literal values are allowed, because then the referenced value can't be changed.
Likewise for
void foo(int* n);
you must pass a pointer.
So for example:
int a = ...;
int& ra = a; // ra references a
foo(&a); // OK
foo(&ra); // OK
foo(a); // Fail, a is not a pointer
foo(ra); // Fail, ra is not a pointer
foo(1); // Fail, the literal 1 is not a pointer
And for the last:
void foo(int n);
With examples:
int a = ...;
int& ra = a; // ra references a
int* pa = &a; // pa points to a
foo(a); // OK, the value of a is copied
foo(ra); // OK, the value of the referenced variable is copied
foo(*pa); // OK, dereferences the pointer, and the value is copied
foo(pa); // Fail, passing a pointer to a function not expecting a pointer
foo(1); // OK, the literal value 1 is copied
operator*
and operator&
Both operator&
(unary) and operator*
(unary) can be overloaded.
This means that if n
is a class type type
, then *n
can literally have any form including, but not limited to type*
, type&
, type
.
An example (stupid, but still a valid example) would be:
struct type {
int x;
};
int& operator&(type& t) {
return t.x;
}
Live demo
You can also have infinite number of pointer indirections. In which case *n
, **n
, ***n
might also yield Type*
as well as Type&
.
As an example, given two functions:
void func_ptr(int*) {}
void func_ref(int&) {}
and the following objects:
int a;
int* b = &a;
int** c = &b;
int*** d = &c;
then, any of the following is valid:
func_ptr(b);
func_ptr(*c);
func_ptr(**d);
func_ref(*b);
func_ref(**c);
func_ref(***d);
Live demo
Are the table and explanations correct? Are there any cases left out of the table (except for derived ones like *&n, pointer to pointer etc.)?
Therefore the table not only is incomplete, but cannot possibly contain all possible cases.
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