C++: *p = &a vs &p = a [duplicate] - c++

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 1 year ago.
Maybe there is an answer to this, but I haven't found it, probably because I do not know what the correct title of my question is.
I'm starting to learn C++, and noticed that when initializing, modifying, and accessing, the behavior is the same in both of these lines.
int *p = &a;
and
int &p = a;
The only difference I see is that later when I use p in the first case, I have to write *p everytime, otherwise I get the address of (probably a since its value equals &a), whereas in the second case I can just write p without the asterisk.
Are those just different syntax for the same thing, or are they different but just happen to give me the same results (in my very basic tests)? Is the compiler doing the same thing in both cases?

Actually, that depends on your program!
For example:
a = 123;
b = 456;
int *p = &a;
// bunch of statements here
if (condition) { p = &b; }
do_stuff(*p);
You can't do this with a reference: Once it's set, it's set.
Another difference of pointers and references in C++ is that (const) references can extend the lifetime of temporary objects:
foo f() {
foo inner_foo;
return inner_foo;
}
const foo_ref& = f();
if the function were to return a pointer to inner_foo:
foo* f() {
foo inner_foo;
return &inner_foo;
}
const foo* p = f();
you would have a pointer to a destructed foo, in a place on the stack that may get used by other variables.
And there are other differences between pointers and references.
You may also want to read the following items in the C++ Super-FAQ:
Why does C++ have both pointers and references?
When should I use references, and when should I use pointers?

The first is a pointer to an object, in your example to an int named a. A pointer holds the memory address of an object in memory. You would have to dereference the pointer in order to access the object it is pointing at.
The second is a reference to an object, in your example to a. A reference is an alias 1, ie another name, for an object. So the two names are effectively referring to, and thus are treated as, the same object, which is why you can use p to access a without dereferencing p.
1: though, most compilers will implement a reference using a pointer, but this is an implementation detail and should not be relied on in code logic.
Another difference is that a pointer can be set to nullptr, and can also be re-assigned to point at a different memory address, eg:
int a, b;
int *p = nullptr;
...
p = &a;
...
p = &b;
Whereas a reference cannot do either of those things. Once initialized, a reference cannot be changed to refer to another object.
As such, taking the address of a reference with operator& will return the address of the object it refers to, whereas taking the address of a pointer will return the address of the pointer itself, not the object it points at.
Likewise, assigning a value to a reference will assign to the object it refers to, whereas assigning a value to a pointer will assign to the pointer itself, not the object it points at.

Related

Interpreting the & sign in C++ [duplicate]

This question already has answers here:
Address-of operator (&) vs reference operator(&)
(3 answers)
Meaning of references, address-of, dereference and pointer
(4 answers)
What are the differences between a pointer variable and a reference variable?
(44 answers)
ampersand '&' operator at end of parameter
(1 answer)
Closed 7 months ago.
My confusion:
Since both the pointers and references use the symbol &, and in pointers & symbol is usually interpreted as "the address of ...", I wonder whether it should be interpreted the same in references.
My theory:
When & sign appears on the right hand side of =, it can be interpreted as "the address of".
When & sign appears on the left hand side of =, it should be associated with references and CAN'T be directly interpreted as "the address of".
My proof:
& in pointers:
int a = 1;
int *p = &a;
The value of pointer variable p is the address of variable a.
In other words, p is a pointer pointing to variable a.
& in references:
int a = 1;
int & b = a;
b is a reference to a.
In other words, the address of reference variable b is the same as the address of variable a.
But the code itself wouldn't be appropriate to directly interpreted it as "the address of reference variable b is the address of variable a", because otherwise then the code should instead be
int a = 1;
int & b = &a;
, and that is incorrect according to C++ syntax.
Error message:
error: cannot bind rvalue '(int)(& a)' to 'int&'
Thanks for replies in advance!
When you use the reference operator for this code block
int a = 1;
int & b = &a;
you are trying to assign an "address" into an "integer" variable which is not allowed. Pointers can have addresses inside them not integer variables. However when you use the reference operator like this
int a = 1;
int & b = a;
b is an integer variable which has the SAME address as a this is why you get the following error
Since there are only so many ASCII symbols, it's inevitable that they get re-used for contradictory purposes, and & is one such character.
It means either address of in a statement or reference to in a variable declaration. Thinking of the "right-hand-side" is close, but it's really just its presence in a statement or, more specifically, an expression. Remember the rules apply in function definitions as well, as in int f(int &a) where there's no RHS in play.
In your example:
int & b = a;
This reads as "b is a reference to a, which is an int".
Keep in mind references might seem similar to addresses as in pointers, but they are not at all the same. A reference is an alias, as in it is entirely equivalent to. A pointer is, by definition, always one degree removed.
That is in the case of:
b = 2;
This assigns directly to b, which is an alias for a, so they both change. To adjust a pointer int *c = &a you would need to do *c = 2 which changes a but does not change c, the address of a remains the same.
Remember you can have references to pointers, pointers to references, and any combination you can dream up, even from nightmares, like int &*&**&***a if you so wish. It's valid! (Just not recommended.)
So things to keep in mind for a simple example of int &b = a:
b and a share the same address
Modifying b always modifies a
To the compiler, b is just an alias for a
b[0] is a syntax error unless a can be indexed as an array
*b is a syntax error unless a can be de-referenced as pointer
Whereas for int *c = a:
c has a different address from a
c is a different variable from a
Modifying c directly does not modify a
Modifying a de-referenced *c does modify a
c behaves like an array, as in c[0] can be used to fetch or modify a
Pointers generally incur an additional level of overhead when de-referencing and "exercising" them
If you're ever wondering what's going on, look at the assembly output of a simple program that uses both pointers and references. The differences can be substantial.

What's the difference between * and & in C?

I'm learning C and I'm still not sure if I understood the difference between & and * yet.
Allow me to try to explain it:
int a; // Declares a variable
int *b; // Declares a pointer
int &c; // Not possible
a = 10;
b = &a; // b gets the address of a
*b = 20; // a now has the value 20
I got these, but then it becomes confusing.
void funct(int a) // A declaration of a function, a is declared
void funct(int *a) // a is declared as a pointer
void funct(int &a) // a now receives only pointers (address)
funct(a) // Creates a copy of a
funct(*a) // Uses a pointer, can create a pointer of a pointer in some cases
funct(&a) // Sends an address of a pointer
So, both funct(*a) and funct(&a) are correct, right? What's the difference?
* and & as type modifiers
int i declares an int.
int* p declares a pointer to an int.
int& r = i declares a reference to an int, and initializes it to refer to i.
C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.
Similarly:
void foo(int i) declares a function taking an int (by value, i.e. as a copy).
void foo(int* p) declares a function taking a pointer to an int.
void foo(int& r) declares a function taking an int by reference. (C++ only)
* and & as operators
foo(i) calls foo(int). The parameter is passed as a copy.
foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p.
foo(&i) takes the address of the int i and calls foo(int*) with that address.
(tl;dr) So in conclusion, depending on the context:
* can be either the dereference operator or part of the pointer declaration syntax.
& can be either the address-of operator or (in C++) part of the reference declaration syntax.
Note that * may also be the multiplication operator, and & may also be the bitwise AND operator.
funct(int a)
Creates a copy of a
funct(int* a)
Takes a pointer to an int as input. But makes a copy of the pointer.
funct(int& a)
Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.
void funct(int &a) declares a function that takes a reference. A reference is conceptually a pointer in that the function can modify the variable that's passed in, but is syntactically used like a value (so you don't have to de-reference it all the time to use it).
Originally in C there were pointers and no references. Very often though we just want to access a value without copying it and the fact that we're passing around an address and not the actual value is an unimportant detail.
C++ introduced references to abstract away the plumbing of pointers. If you want to "show" a value to a function in C++ then references are preferable. The function is guaranteed that a reference is not null and can access it as if it were the value itself. Pointers are still necessary for other purposes, for example, you can "re-aim" a pointer or delete with a pointer but you can't do so with a reference.
Their functionality does overlap and without a bit of history it should confuse you that we have both.
So the answer to your direct question is that very often there is no difference. That said, f(int*) can be useful if you want the function to be able to check if the pointer is null. If you're using C then pointers are the only option.
The meaning of * is dependent on context. When in a data or function argument declaration, it is a datatype qualifier, not an operator int* is a datatype in itself. For this reason it is useful perhaps to write:
int* x ;
rather than:
int *x ;
They are identical, but the first form emphasises that it the * is part of the type name, and visually distinguishes it from usage as dereference operator.
When applied to an instantiated pointer variable, it is the dereference operator, and yields the the value pointed to.
& in C is only an operator, it yields the address (or pointer to) of an object. It cannot be used in a declaration. In C++ it is a type qualifier for a reference which is similar to a pointer but has more restrictive behaviour and is therefore often safer.
Your suggestion in the comment here:
funct(&a) // Sends an address of a pointer
is not correct. The address of a is passed; that would only be "address of a pointer" is a itself is a pointer. A pointer is an address. The type of an address of a pointer to int would be int** (a pointer to a pointer).
Perhaps it is necessary to explain the fundamentals of pointer and value variables? A pointer describes the location in memory of a variable, while a value describes the content of a memory location.
<typename>* is a pointer-to-<typename> data type.
&*<value-variable> yields the address or location of <variable> (i.e. a pointer to <variable>),
**<pointer-variable> dereferences a pointer to yield the the value at the address represented by the pointer.
So given for example:
int a = 10 ;
int* pa = &a ;
then
*pa == 10
When you do func(&a) that's called a "call by reference" that means your parameter "a" can actually be modified within the function and any changes made will be visible to the calling program.
This is a useful way if you want to return multiple values from a function for example:
int twoValues(int &x)
{
int y = x * 2;
x = x + 10;
return y;
}
now if you call this function from your main program like this:
int A, B;
B = 5;
A = twoValues(B);
This will result in:
A holding the value 10 (which is 5 * 2)
and B will hold the value 15 (which is 5 + 10).
If you didn't have the & sign in the function signature, any changes you make to the parameter passed to the function "twoValues" would only be visible inside that function but as far as the calling program (e.g. main) is concerned, they will be the same.
Now calling a function with a pointer parameter is most useful when you want to pass an array of values or a list. Example:
float average ( int *list, int size_of_list)
{
float sum = 0;
for(int i = 0; i < size_of_list; i++)
{
sum += list[i];
}
return (sum/size_of_list);
}
note that the size_of_list parameter is simply the number of elements in the array you are passing (not size in bytes).
I hope this helps.
C++ is different from c in many aspects and references is a part of it.
In terms of c++ context:
void funct(int *a) // a is declared as a pointer
This corelates to the use of pointers in c..so, you can compare this feature to that of c.
void funct(int &a) // a now receives only pointers (address)
This would lead to the reference usage in c++...
you cannot corelate this to that of c..
Here is a good q&a clarifying differences between these two.
What are the differences between a pointer variable and a reference variable in C++?

Why declare a constant pointer using the const keyword when the reference (const pointer) is available?

For example:
I could make a constant pointer, which points to an object that I can change through my pointer. The pointer cannot be reassigned:
MyObj const *ptrObj = MyObj2
Why would I use this over:
MyObj &ptrObj = MyObj2
What you have there isn't a const pointer, it's a pointer to a const object - that is, the pointer can be changed but the object can't. A const pointer would be:
MyObj *const ptrObj = &MyObj2;
As to why you might prefer it over a reference, you might want the flexibility of using the NULL special value for something - you don't get that with a reference.
You got it wrong. What you have is a mutable pointer to a constant object:
T const * p;
p = 0; // OK, p isn't const
p->mutate(); // Error! *p is const
T const & r = *p; // "same thing"
What you really want is a constant pointer to mutable object:
T * const p = &x; // OK, cannot change p
T & r = x; // "same thing"
p->mutate(); // OK, *p is mutable
Indeed, references are morally equivalent to constant pointers, i.e. T & vs T * const, and the constant version T const & vs T const * const.
If you insist on getting some advice, then I'd say, "don't use pointers".
The important difference between a pointer and a reference is how many objects they may refer to. A reference always refers to exactly one object. A pointer may refer to zero (when the pointer is null), one (when the pointer was assigned the location of a single object) or n objects (when the pointer was assigned to some point inside an array).
The ability of pointers to refer to 0 to n objects means that a pointer is more flexible in what it can represent. When the extra flexibility of a pointer is not necessary it is generally better to use a reference. That way someone reading your code doesn't have to work out whether the pointer refers to zero, one or n objects.

What is the difference between a reference and a pointer?

Could someone please explain the difference to me in very small words? I have never understood this and am very confused in my current project. What I am trying to do is fix this code:
const Multinumber& Pairs::operator+(const Multinumber &rhs) const
{
const Pairs &_rhs = dynamic_cast<const Pairs &>(rhs);
Pairs toreturn(_rhs.X_value+X_value,_rhs.Y_value+Y_value);
return toreturn; //reference to local variable? fix this?
}
Now my compiler tells me that this is a reference to a local variable, but it won't let me turn toreturn into a pointer, because they are somehow different from references. And then, I am also working on a set class, which is supposed to hold references or pointers to objects of an abstract class. I am totally confused. Any help would be much appreciated.
First, your signature is wrong. It should be:
Multinumber Pairs::operator+(const Multinumber &rhs) const;
operator+ should return a new object, not a reference to either argument.
As for the difference between references and pointers, this detailed question right here on SO. It covers all the basics, and the some.
You do seem very confused :) Ok, so:
Essentially, a pointer is just a variable that stores the address of another variable. For instance, suppose I have an int called i, I can store its address in a pointer p:
int i = 23;
int *p = &i; // p has type int* (pointer to int) and stores &i (the address of i)
If I then want to change the thing it points to (i.e. the variable whose address it stores), I just assign to *p -- this is the syntax used to denote the thing pointed to. In this case, *p refers to i. Thus:
*p = 9; // sets i to 9 (since *p is i)
I can reseat the pointer (i.e. make it point to something else) just by assigning to p, i.e.
int j = 84;
p = &j; // store j's address in p, overwriting what was there before (i.e. i's address)
*p = 18; // sets j to 18 (since *p is now j)
Now, a reference is slightly different. A reference creates an alias for a variable:
int i = 23;
int& r = i; // r has type int& (reference to int) and refers to i
Note that references may be implemented in terms of pointers (or they may not, particularly when the compiler starts optimizing things), but that's irrelevant from the programming perspective -- all that matters to us here is the way the language works.
If you want to change the thing referred to (i.e. i in this case), you just do:
r = 9; // sets i to 9 (since r is an alias for i)
Unlike pointers, references cannot be reseated. As just shown, assigning to r changes the thing you're referring to (i), not the reference itself. Furthermore, because references cannot be reseated, they must be initialized immediately. This is not the case with pointers. In other words:
int *p; // legal
int& r; // bad
One final basic difference is that pointers can be NULL, indicating that they are not pointing to anything. This just means they contain the address 0. References must always refer to an actual object. This difference can be important to implementers, because they can then use pointers to implement a Maybe type, i.e. if the pointer is not NULL, then make use of the pointed-to object, otherwise do something else. They can't do the same thing with references.
Hope that's clear as regards pointers vs. references!
Now, regarding your operator+ -- the purpose of an addition operator is to add two objects and return a new object representing their sum. So if I had a 2D vector type, I might write an operator+ for it as follows:
Vec2 operator+(const Vec2& lhs, const Vec2& rhs)
{
return Vec2(lhs.x+rhs.x, lhs.y+rhs.y);
}
In your code, you are trying to return a local object toreturn by reference -- this doesn't work, because toreturn ceases to exist at the end of the operator. Instead, you should return by value here. Incidentally, you would encounter the same problem if you tried to return a pointer, e.g.
Vec2* operator+(const Vec2& lhs, const Vec2& rhs)
{
Vec2 result(lhs.x+rhs.x, lhs.y+rhs.y);
return &result; // bad!
}
In that code, result ceases to exist at the end of the operator, so the pointer you return would end up pointing to an invalid location. Bottom line -- don't try anything fancy, return by value in this sort of situation.
Pointer has some address where the object is. And the reference is as the alias for the pointer and it means that you don't have to dereference it. But the usage is similar - don't copy objects, only work with the origin.
You have the variable toreturn as a local variable which means that the compiler generates the destructor for this object at the end of method. So you are trying to return destroyed object.

C++ Returning Pointers/References

I have a fairly good understanding of the dereferencing operator, the address of operator, and pointers in general.
I however get confused when I see stuff such as this:
int* returnA() {
int *j = &a;
return j;
}
int* returnB() {
return &b;
}
int& returnC() {
return c;
}
int& returnC2() {
int *d = &c;
return *d;
}
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically "appended" c?
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Assume a, b, c are initialized as integers as Global.
Can someone validate if I am correct with all four of my questions?
Although Peter answered your question, one thing that's clearly confusing you is the symbols * and &. The tough part about getting your head around these is that they both have two different meanings that have to do with indirection (even excluding the third meanings of * for multiplication and & for bitwise-and).
*, when used as part of a type
indicates that the type is a pointer:
int is a type, so int* is a
pointer-to-int type, and int** is a
pointer-to-pointer-to-int type.
& when used as part of a type indicates that the type is a reference. int is a type, so int& is a reference-to-int (there is no such thing as reference-to-reference). References and pointers are used for similar things, but they are quite different and not interchangable. A reference is best thought of as an alias, or alternate name, for an existing variable. If x is an int, then you can simply assign int& y = x to create a new name y for x. Afterwords, x and y can be used interchangeably to refer to the same integer. The two main implications of this are that references cannot be NULL (since there must be an original variable to reference), and that you don't need to use any special operator to get at the original value (because it's just an alternate name, not a pointer). References can also not be reassigned.
* when used as a unary operator performs an operation called dereference (which has nothing to do with reference types!). This operation is only meaningful on pointers. When you dereference a pointer, you get back what it points to. So, if p is a pointer-to-int, *p is the int being pointed to.
& when used as a unary operator performs an operation called address-of. That's pretty self-explanatory; if x is a variable, then &x is the address of x. The address of a variable can be assigned to a pointer to the type of that variable. So, if x is an int, then &x can be assigned to a pointer of type int*, and that pointer will point to x. E.g. if you assign int* p = &x, then *p can be used to retrieve the value of x.
So remember, the type suffix & is for references, and has nothing to do with the unary operatory &, which has to do with getting addresses for use with pointers. The two uses are completely unrelated. And * as a type suffix declares a pointer, while * as a unary operator performs an action on pointers.
In returnA() I'm asking to return a pointer; just to clarify this works because j is a pointer?
Yes, int *j = &a initializes j to point to a. Then you return the value of j, that is the address of a.
In returnB() I'm asking to return a pointer; since a pointer points to an address, the reason why returnB() works is because I'm returning &b?
Yes. Here the same thing happens as above, just in a single step. &b gives the address of b.
In returnC() I'm asking for an address of int to be returned. When I return c is the & operator automatically appended?
No, it is a reference to an int which is returned. A reference is not an address the same way as a pointer is - it is just an alternative name for a variable. Therefore you don't need to apply the & operator to get a reference of a variable.
In returnC2() I'm asking again for an address of int to be returned. Does *d work because pointers point to an address?
Again, it is a reference to an int which is returned. *d refers to the original variable c (whatever that may be), pointed to by c. And this can implicitly be turned into a reference, just as in returnC.
Pointers do not in general point to an address (although they can - e.g. int** is a pointer to pointer to int). Pointers are an address of something. When you declare the pointer like something*, that something is the thing your pointer points to. So in my above example, int** declares a pointer to an int*, which happens to be a pointer itself.
Tyler, that was very helpful explanation, I did some experiment using visual studio debugger to clarify this difference even further:-
int sample = 90;
int& alias = sample;
int* pointerToSample = &sample;
Name Address Type
&alias 0x0112fc1c {90} int *
&sample 0x0112fc1c {90} int *
pointerToSample 0x0112fc1c {90} int *
*pointerToSample 90 int
alias 90 int &
&pointerToSample 0x0112fc04 {0x0112fc1c {90}} int * *
Memory Layout
PointerToSample Sample/alias
_______________......____________________
0x0112fc1c | | 90 |
___________|___.....__|________|_______...
[0x0112fc04] ... [0x0112fc1c
In returnC() and returnC2() you are not asking to return the address.
Both these functions return references to objects.
A reference is not the address of anything it is an alternative name of something (this may mean the compiler may (or may not depending on situation) use an address to represent the object (alternatively it may also know to keep it in register)).
All you know that a reference points at a specific object.
While a reference itself is not an object just an alternative name.
All of your examples produce undefined run-time behavior. You are returning pointers or references to items that disappear after execution leaves the function.
Let me clarify:
int * returnA()
{
static int a; // The static keyword keeps the variable from disappearing.
int * j = 0; // Declare a pointer to an int and initialize to location 0.
j = &a; // j now points to a.
return j; // return the location of the static variable (evil).
}
In your function, the variable j is assigned to point to a's temporary location. Upon exit of your function the variable a disappears, but it's former location is returned via j. Since a no longer exists at the location pointed to by j, undefined behavior will happen with accessing *j.
Variables inside functions should not be modified via reference or pointer by other code. It can happen although it produces undefined behavior.
Being pedantic, the pointers returned should be declared as pointing to constant data. The references returned should be const:
const char * Hello()
{
static const char text[] = "Hello";
return text;
}
The above function returns a pointer to constant data. Other code can access (read) the static data but cannot be modified.
const unsigned int& Counter()
{
static unsigned int value = 0;
value = value + 1;
return value;
}
In the above function, the value is initialized to zero on the first entry. All next executions of this function cause value to be incremented by one. The function returns a reference to a constant value. This means that other functions can use the value (from afar) as if it was a variable (without having to dereference a pointer).
In my thinking, a pointer is used for an optional parameter or object. A reference is passed when the object must exist. Inside the function, a referenced parameter means that the value exists, however a pointer must be checked for null before dereferencing it. Also, with a reference, there is more guarantee that the target object is valid. A pointer could point to an invalid address (not null) and cause undefined behavior.
Semantically, references do act as addresses. However, syntactically, they are the compiler's job, not yours, and you can treat a reference as if it is the original object it points to, including binding other references to it and having them refer to the original object too. Say goodbye to pointer arithmetic in this case.
The downside of that is that you can't modify what they refer to - they are bound at construct time.