Pass by reference notation - c++

My question is really straightforward and I believe understandable.
I've made this simple snippet to illustrate my conflict when I'm passing values by reference.
int main() {
int a = 1;
int &b = a;
}
I know that this is the correct way to do it but how does it make sense to take the address of b and make it equal to the value of a. Logically it should be: int &b = &a;

Many operators are context-sensitive. The & "operator" could mean three different things depending on context:
It could be used when defining a reference
int& r = a; // The variable r is a reference of the variable a
It could be used to get a pointer to something
int* p = &a; // Here & is the address-of operator which returns a pointer
// Here it makes p point to the variable a
It could be the bitwise AND operator
0x53 & 0x0f // Here's a bitwise AND operation, the result is 0x03

You're mistaken by the syntax. This is unhappy, but & is both the addressof operator and the token meaning "referente to".
int &b = a;
This declares the variable b to be of type int& (reference to an int) and initialized to a. No address whatsoever.

Related

C++: What is a de-reference actually doing?

I am reading through Stroustrup's 4th edition : The C++ Programming Language. I have a python/java background so the first 4 chapters are fine so far.
In Chapter 3 I saw:
complex& operator+=(complex z) { re+=z.re , im+=z.im; return ∗this; }
That began a day long attempt to write this question:
First I figured out that it is returning a reference to the object and not a copy. As I was able to confirm in this question.
And I was able to understand the difference between returning a reference into a reference variable vs. a regular variable from this question
And I did my own trial
class Test {
public:
Test():x{5}{}
int x;
void setX(int a) {x = a;}
Test& operator+=(Test z) {x+=z.x; return *this;}
// the keyword this is a pointer
Test* getTest() {return this;}
// but I can return the reference by *this
Test& getTest1() {return *this;}
// or I can return a copy
Test getTest2() {return *this;}
};
That lead me to question why it is called de-reference, so I did this trial
int x = 8;
int* p = &x;
int y = *p;
int& z = *p;
x++; // let's have some fun
std::cout << y << std::endl;
std::cout << z << std::endl;
As expected y = 8 and z = 9, so how did the de-reference return the address in one case, and the value in the other? More importantly how is C++ making that distinction?
It's exactly like in your Test class functions.
int y = *p;
int& z = *p;
y is a copy of what p points to.
z is a reference to (not an address) what p points to. So changing z changes *p and vice-versa. But changing y has no effect on *p.
As expected y = 8 and z = 9, so how did the de-reference return the address in one case, and the value in the other? More importantly how is C++ making that distinction?
The de-reference returned the actual thing referenced in both cases. So there is no distinction for C++ to make. The difference is in what was done with the result of the dereference.
If you do int j = <something>; then the result of the something is used to initialize j. Since j is an integer, the <something> must be an integer value.
If you do int &j = <something>; then the result of the something is still used to initialize j. But now, j is a reference to an integer, and the <something> must be an integer, not just an integer value.
So, what *this does is the same in both cases. How you use a value doesn't affect how that value is computed. But how you use it does affect what happens when you use it. And these two pieces of code use the dereferenced object differently. In one case, its value is taken. In the other case, a reference is bound to it.
It's possible to consider a pointer int* p as pointing to an address where data of type int resides. When you de-reference this, the system retrieves the value at that memory address (the address is the actual value of p itself). In the case of int y = *p; you put a copy of that int value on the stack as the locator value y.
On the other hand, de-referencing on the left-hand side in *p = 13; means you are replacing the int value *p stored at the memory address denoted by the value of p with the right-hand-side value 13.
The reference lvalue int& z in int& z = *p; is not a copy of the int value pointed to by p but rather a left-hand side reference to whatever is at the particular memory address returned by *p (i.e. the actual value held by p itself).
This doesn't mean much difference in your contrived case, but e.g. given a Foo class with a Foo::incrementCount() value,
Foo* p = new Foo();
p->incrementCount();
Foo& ref = *p;
ref.incrementCount();
The same method for the same instance will be called twice. In contrast, Foo foo = *p will actually copy the entire Foo instance, creating a separate copy on the stack. Thus, calling foo.incrementValue() won't affect the separate object still pointed to by p.

Pointers: initialisation vs. declaration

I am a C++ noob and I am quite sure this is a stupid question, but I just do not quite understand why an error arises (does not arise) from the following code:
#include <iostream>
using namespace std;
int main()
{
int a,*test;
*test = &a; // this error is clear to me, since an address cannot be
// asigned to an integer
*(test = &a); // this works, which is also clear
return 0;
}
But why does this work too?
#include <iostream>
using namespace std;
int main()
{
int a, *test= &a; // Why no error here?, is this to be read as:
// *(test=&a),too? If this is the case, why is the
// priority of * here lower than in the code above?
return 0;
}
The fundamental difference between those two lines
*test= &a; // 1
int a, *test= &a; // 2
is that the first is an expression, consisting of operator calls with the known precedence rules:
operator=
/\
/ \
/ \
operator* operator&
| |
test a
whereas the second is a variable declaration and initialization, and equivalent to the declaration of int a; followed by:
int* test = &a
// ^^ ^^ ^^
//type variable expression giving
// name initial value
Neither operator* nor operator= is even used in the second line.
The meaning of the tokens * and = (and & as well as ,) is dependent on the context in which they appear: inside of an expression they stand for the corresponding operators, but in a declaration * usually appears as part of the type (meaning "pointer to") and = is used to mark the beginning of the (copy) initialization expression (, separates multiple declarations, & as "reference to" is also part of the type).
int a, *test= &a;
is equivalent of:
int a;
int* test = &a;
and perfectly valid as you initialize test which has a type of pointer to int with an address of variable a which has a type of int.
You're confusing two uses for *.
In your first example, you're using it to dereference a pointer.
In the second example, you're using it to declare a "pointer to int".
So, when you use * in a declaration, it's there to say that you're declaring a pointer.
You are actually doing an initialisation like this in first case,
int *test = &a;
It means that, you are initialising a pointer for which you mention * to tell the compiler that its a pointer.
But after initialisation doing a *test (with an asterisk) means that you are trying to access the value at the address assigned to pointer test.
In other words, doing an *test means you are getting the value of a because address of a is stored into pointer test which is done by just doing a &a.
& is the operator to get the address of any variable. And * is the operator to get the value at address.
So initialisation & assignment are inferred differently by the compiler even if the asterisk * is present in both the cases.
You just hit two of the horrible language design spots: squeezing declarations into one line and reuse of * symbol for unrelated purposes. In this case * is used to declare a pointer (when it is used as part of type signature int a,*test;) and to deference a pointer (when it is used as a statement *test = &a;). The good practice would be to declare variables one at a time, to use automatic type deduction instead of type copypasting and to use dedicated addressof method:
#include <memory> // for std::addressof
int a{};
auto const p_a{::std::addressof(a)};
There's a subtle difference there.
When you declare int a, *test, you're saying "declare a as an integer, and declare test as a pointer to an integer, with both of them uninitialized."
In your first example, you set *test to &a right after the declarations. That translates to: "Set the integer that test points to (the memory address) to the address of a." That will almost certainly crash because test wasn't initialized, so it would either be a null pointer or gibberish.
In the other example, int a, *test= &a translates to: "declare a as an uninitialized integer, and declare test as a pointer initialized to the address of a." That's valid. More verbosely, it translates to:
int a, *test;
test = &a;

How does this return a reference?

I've been trying to learn how to use a singleton design pattern and stumbled across this:
static S& getInstance()
{
static S instance;
return instance;
}
I noticed here that it returns instance, shouldn't it be supposed to return an instance&?
Edit: I should also mention that the compiler doesn't seem to be making any complaints.
return instance; does return a reference to instance. That is just like
int& r = a;
for some int a creates a reference to a without needing to write a& or something like this.
No, it's correct as written. The compiler will create and return a reference to instance from the function getInstance.
You ask whether it should be instance&. First of all, that is not syntactically valid. What about &instance then? That would take the address of instance and would, therefore, return an instance *.
The multiple uses of the & operator are a common source of confusion. Here's a quick "cheat-sheet" that doesn't use complex terminology from the standard:
The binary (two argument) version of & is applied against two instances of variables and represents bitwise AND (except when overloaded).
unsigned int a = 7;
unsigned int b = 3;
unsigned int c = a & b; // c = 3
The unary (one argument) version of & when applied to a type denotes a reference to a type. Example:
int a = 7;
int& ref_a = a; // ref_a is a reference to a
The unary (one argument) version of & when applied to a variable denotes the address-of operator and yields a pointer to the variable.
int a = 7;
int* ptr_a = &a;

declaration of reference and pointer in c++

For example, if F is a reference to an integer, where the reference is not permitted to be pointed to a new object once it is initially pointed to one.
Can I write to declaration like: const int & F?
I am confused about reference and pointer, because they both represent the address of something, but we always write parameter use reference as: const & F, I understand that this is to reduce the copy and does not allow others to change it, but are there any other meanings? and why do we need "const" after a function declaration like: int F(int z) const; this const makes the return type const or everything in the function const?
One more example,
void F(int* p)
{
p+=3;
}
int z=8;
F(&z);
std::cout<<z<<std::endl;
What is the output for z since z is a reference, and I pass it as a pointer who points to an integer.Increasing p by 3 just makes the address different and does not change its value?
Just a first pass at some answers - if anything is unclear please comment and I'll try to elaborate.
int a = 3;
declares an integer, a, with the initial value 3, but you are allowed to change it. For example, later you can do
a = 5; // (*)
and a will have the value 5. If you want to prevent this, you can instead write
const int a = 3;
which will make the assignment (*) illegal - the compiler will issue an error.
If you create a reference to an integer, you are basically creating an alias:
int& b = a;
, despite appearances, does not create a new integer b. Instead, it declares b as an alias for a. If a had the value 3 before, so will b, if you write b = 6 and print the value of a, you will get 6 as well. Just as for a, you can make the assignment b = 6 illegal by declaring it as const:
const int& b = a;
means that b is still an alias for a, but it will not be used to assign a different value to a. It will only be used to read the value of a. Note that a itself still may or may not be constant - if you declared it as non-const you can still write a = 6 and b will also be 6.
As for the question about the pointers: the snippet
void F(int* p) {
p += 3;
}
int z = 8;
F(&z);
does not do what you expected. You pass the address of z into the function F, so inside F, the pointer p will point to z. However, what you are doing then, is adding 3 to the value of p, i.e. to the address that p points to. So you will change to pointer to point at some (semi)random memory address. Luckily, it's just a copy, and it will be discarded. What you probably wanted to do, is increment the value of the integer that p points to, which would be *p += 3. You could have prevented this mistake by making the argument a int* const, meaning: the value of p (i.e. address pointed to) cannot be changed, but the value it points to (i.e. the value of z, in this case) can. This would have made *p += 3 legal but not the "erroneous" (unintended) p += 3. Other versions would be const int* p which would make p += 3 legal but not *p += 3, and const int* const` which would have allowed neither.
Actually, the way you have written F is dangerous: suppose that you expand the function and later you write (correctly) *p += 3. You think that you are updating the value of z whose address you passed in, while actually you are updating the value of a more-or-less random memory address. In fact, when I tried compiling the following:
// WARNING WARNING WARNING
// DANGEROUS CODE - This will probably produce a segfault - don't run it!
void F(int* p) {
p += 3; // I thought I wrote *p += 3
// ... Lots of other code in between, I forgot I accidentally changed p
*p += 3; // NOOOOOOOOOOO!
}
int main()
{
int z=8;
F(&z);
std::cout << z;
return 0;
}
I got a segmentation fault, because I'm writing at an address where I haven't allocated a variable (for all I know I could have just screwed up my boot sector).
Finally, about const after a function declaration: it makes the this pointer a const pointer - basically the compiler emits const A* this instead of just A* this. Conceptually, it states your intention that the function will not change the state of the class, which usually means it won't change any of the (internal) variables. For example, it would make the following code illegal:
class A {
int a;
void f() const {
a = 3; // f is const, so it cannot change a!
}
};
A a;
a.f();
Of course, if the function returns something, this value can have its own type, for example
void f();
int f();
int& f();
const int f();
const int& f();
are functions that return nothing, a (copy of) an integer, a (reference to) an integer, a constant (copy of) an integer, and a constant reference of an integer. If in addition f is guaranteed not to change any class fields, you can also add const after the brackets:
void f() const;
int f() const;
int& f() const;
const int f() const;
const int& f() const;
The way I remember the difference between references and pointers is that a reference must exist and the reference cannot change.
A pointer can be changed, and usually needs to be checked against NULL or tested to verify it points to a valid object.
Also, an object passed by reference can be treated syntactically like it was declared in the function. Pointers must use deferencing syntax.
Hope that helps.
You are confusing things.
First of all int z=8; F(&z); here z IS NOT a reference.
So let me start with the basics:
when found in a type declaration the symbol & denotes a reference, but in any other context, the symbol & means address of.
Similar, in a type declaration * has the meaning of declaring a pointer, anywhere else it it the dereferencing operator, denoting you use the value at an address.
For instance:
int *p : p is a pointer of type int.
x = *p : x is assigned the value found at address p.
int &r = a : r is reference of type int, and r refers the variable a.
p = &a : p is assigned the address of variable a.
Another question you have: the const at the end of a function, like int f(int x) const. This can be used only on non-static class methods and specifies that the function does not modify the object. It has nothing to do with the return value.

Assigning int value to an address

I thought the following codes were correct but it is not working.
int x, *ra;
&ra = x;
and
int x, ra;
&ra = x;
Please help me if both of these code snippets are correct. If not, what errors do you see in them?
Your both expressions are incorrect, It should be:
int x, *ra;
ra = &x; // pointer variable assigning address of x
& is ampersand is an address of operator (in unary syntax), using & you can assign address of variable x into pointer variable ra.
Moreover, as your question title suggests: Assigning int value to an address.
ra is a pointer contains address of variable x so you can assign a new value to x via ra
*ra = 20;
Here * before pointer variable (in unary syntax) is deference operator gives value at the address.
Because you have also tagged question to c++ so I think you are confuse with reference variable declaration, that is:
int x = 10;
int &ra = x; // reference at time of declaration
Accordingly in case of the reference variable, if you want to assign a new value to x it is very simply in syntax as we do with value variable:
ra = 20;
(notice even ra is reference variable we assign to x without & or * still change reflects, this is the benefit of reference variable: simple to use capable as pointers!)
Remember reference binding given at the time of declaration and it can't change where pointer variable can point to the new variable later in the program.
In C we only have pointer and value variables, whereas in C++ we have a pointer, reference and value variables. In my linked answer I tried to explain differences between pointer and reference variable.
Both are incorrect.
When you declare a pointer, you assign it the address of a variable. You are attempting the other way round. The correct way would be:
int x,*ra;
ra = &x;
Both of those causes, in the way you have them in your question, undefined behavior.
For the first, you don't initialize the pointer, meaning it points to a random location (or NULL if the variable is global).
For the second, you try to change the address the variable is located at, which (if it even would compile) is not allowed.
Here's some annotated code:
int main () {
// declare an int variable
int x = 0;
// declare a pointer to an int variable
int *p;
// get the memory address of `x`
// using the address-of operator
&x;
// let `p` point to `x` by assigning the address of `x` to `p`
p = &x;
// assign `x` a value directly
x = 42;
// assign `x` a value indirectly via `p`
// using the dereference operator
*p = 0;
// get the value of `x` directly
x;
// get the value of `x` indirectly via `p`
// using the dereference operator
*p;
}
Note that dereferencing a pointer that doesn't point to a valid object of the specified type is not allowed.
So you normally shouldn't do things like the following (unless you really know what you are doing):
*(int*)(12345) = 42; // assign an integer value to an arbitrary memory address
Here is my 2 cent.
If you are going onto understanding pointer in C. First make the distinction between * the operator and * the type qualifier/specifier.
See that in C * is a syntaxique element that can plays both role but never at the same time. A type qualifier:
int a;
int * c = &a;
int * my_function_returning_pointer();
And for getting the proper int. As an operator. ( *c is an alias of a)
*c = 9;
I admit that is quite confusing and can trap a lot of beginner. Make sure that you recognize when * is used as an operator or when it is used as a type qualifier.
The same things apply to & although it is less often used as type qualifier.
int & f = returning_a_reference();
int my_function( int & refParam);
It is more often use for getting the address of an object. Thus it is used as an operator.
c = &f;
case 1:
int x,*ra;
&ra = x;
it is wrong in c, because in c we can point to a memory location by using a pointer ( i.e *ra in your case ). this can be done as fallows
int x, *ra; x ---------
ra=&x; ra --->1000 | value |
----------
NOTE : with out initializing a variable we can't use pointer to hold the address of that variable, so you better to first initialize variable, then set pointer to that memory location.
int x, *ra;
x=7;
ra=&x;
Fallowing may be helpful to you:
problems(mistake we do ) in handling pointers :
1.)
int a ,*p;
p=a; // assigning value instead of address. that leads to segmentation fault at run time.
2)
int a, *p;
&p=a; // look at here wrong assignment
3)
char *p="srinivas"
strcat(p, "helo" ) ; // we cant add a substring to the constant string.
4) int a=5, *p;
p=5; // the pointer here will points to location 5 in the memory, that may damage whole system, be care full in these type of assignments.