Reference to Pointer Type - c++

#include <iostream>
using namespace std;
int main(void)
{
int num[5];
const int* &ref = num;
return 0;
}
I've read a C++ book which mentioned if a reference variable is referencing to:
a variable where the type is different but can be converted.
a variable that is not a Lvalue.
As long as the referencing variable is declare as const, the above 2 cases will be solved by using a method where the compiler will create a storage and the value will be placed into it while the identifier of the referencing variable is treated as the identifier for that particular storage location . Below is the demonstration code .
Case 1
#include <iostream>
using namespace std;
int main(void)
{
int num = 5;
const long long &ref = num; //the value 5 is place in a new storage where ref is the identifier
return 0;
}
Case 2:
#include <iostream>
using namespace std;
int main(void)
{
int num = 5;
const int &ref = num + 1; //expression num + 1 evaluated and store in new storage with identifier ref
return 0;
}
Since this 2 cases is valid, how come the case inside The Code: is invalid?
My logic is since the name of the array when used will be converted to pointer to the first element of the array , thus the compiler should've spotted this is not a lvalue and a new storage will be created to store that address along and of course , the referencing variable name will be taken as the identifier for that location .
Note : I know this is slightly out of topic , but may I know whether an array name is Lvalue or not? Just a simple yes or no will do , since changing the code to int &ref = num I assume it's not a lvalue , but I just need further confirmation.
Thank you.

You reference variable is not declared const.
There's a difference between const int * and int * const, and you've picked the wrong one.
Your example (ii) is invalid for the same reason, it should be const int &ref = num + 1;
For your Note, I'm not sure that a simple yes or no will do. A simple array name is an lvalue, referring to the array. However, in most contexts it decays to a pointer-to-first-element, which is an rvalue pointer.

Related

why can we increment the dereferenced pointer to a constant data in C++?

I was surprised that c++ allows incrementing dereferenced pointer to a constant data, which it should not allow through a pointer to a const data. Consider the code:
#include<iostream>
#include<climits>
using namespace std;
int main(){
int x = 2;
const int *xPtr2 = &x;
*xPtr2++;
cout << x << endl;
}
But still the value of x is 2. That means *xPtr2 was not actually incremented. I also tried *xPtr2 = 3, but this time it shows compilation error. Why is it so?
Here the precedence of ++ is more than that of *. Hence
*xPtr2++
is equivalent to
*(xPtr2++)
Since xPtr2 is not a constant pointer but a pointer to constant data, incrementing xPtr2 and dereferencing it is fine in this case (but not others) and hence no compilation error is caused.
The ++ operator has precedence over dereferencing. Basically you're dereferencing the pointer that has been incremented.
For the behavior you're trying to accomplish, you should wrap the pointer in parens.
(*xPtr2)++;
Same goes for assigning - you're trying to assign an int to a int *. It would work with parens.
(*xPtr2) = 3;
See your example in ideone.
You have mentioned
dereferencing pointer to constant data
So, lets consider the following code
#include <stdio.h>
int main() {
const int foo = 0xdead;
int* bar = (int*) &foo;
*bar = 0xcafe;
printf("const int foo = %#x", foo);
return 0;
}
Output : const int foo = 0xcafe
In C, C++ const is just a compile time modifier for variables. This means that the compiler wants no modification to a const at compile time. At runtime there is no concept of const => all local variables are stored in stack, all static and global variables are stored in .data section. Thus you can dereference a const and modify it only at runtime

Passing a constant reference into a function

I am trying to pass a constant integer into a function using pass by reference.
#include <iostream>
using namespace std;
int test(int& num);
// changes a constant variable
int main() {
int loopSize = 7;
const int SIZE = loopSize;
cout<<SIZE<<endl;
test(loopSize);
cout<<SIZE;
return 0;
}
int test(int& num){
num -= 2;
}
However, the output is never updated.
SIZE and loopSize are two different objects. Even though SIZE started its life with loopSize's value at the time, changing one won't change the other. SIZE is not a reference.
Indeed, since SIZE is a constant you could never reasonably expect it to change anyway!
Is it possible that you intended to write the following?
const int& SIZE = loopSize;
// ^
You are changing loopSize and printing SIZE, so obviously the value won't change. Also, SIZE is a const, it won't change anyway.

Pointer Confusion with C++

I am very confused with c++ pointers and reference operators. My main confusion is the following (simple ) code:
#include <iostream>
using namespace std;
void changeInt(int &a)
{
a *= 3;
}
int main()
{
int n = 3;
changeInt(n);
cout << n << endl;
return 0;
}
Mainly, I am confused as to why changing the address (&a) changes the actual variable (n). When I first attempted this problem this was my code:
#include <iostream>
using namespace std;
void changeInt(int &a)
{
*a *= 3;
}
int main()
{
int n = 3;
changeInt(n);
cout << n << endl;
return 0;
}
But this gives me an error. Why is it that when I change the address it changes the variable, but when I change the value pointed by the address I get an error?
Your second example is not valid C++, you can only dereference a pointer (or an object whose type overload operator*, which is not your case).
Your first example pass the parameter by reference (int &a is not "the address of a", it is a reference to a), which is why a change to a really is a change to the object being passed by the function (in you case, n)
The ampersand (&) in that context means a reference, not the "address". E.g.:
int some_int;
int & a = some_int; // Declare 'a', a reference to 'some_int'
int * p = &some_int; // '&' in this context is "the address of" 'some_int'
A reference is equivalent to a pointer in many ways, but it behaves like a value type.
See this thread and the wikipedia entry to learn more.
The ampersand indicates that a variable is passed by reference to your function -- but inside the function the variable is treated as if it were passed by value. This is syntactic sugar, to make writing code that accepts references simpler to understand.

How to convert int to const int to assign array size on stack?

I am trying to allocate a fixed size on stack to an integer array
#include<iostream>
using namespace std;
int main(){
int n1 = 10;
const int N = const_cast<const int&>(n1);
//const int N = 10;
cout<<" N="<<N<<endl;
int foo[N];
return 0;
}
However, this gives an error on the last line where I am using N to define a fixed
error C2057: expected constant expression.
However, if I define N as const int N = 10, the code compiles just fine.
How should I typecast n1 to trat it as a const int?
I tried : const int N = const_cast<const int>(n1) but that gives error.
EDIT : I am using MS VC++ 2008 to compile this... with g++ it compiles fine.
How should I typecast n1 to treat it as a const int?
You cannot, not for this purpose.
The size of the array must be what is called an Integral Constant Expression (ICE). The value must be computable at compile-time. A const int (or other const-qualified integer-type object) can be used in an Integral Constant Expression only if it is itself initialized with an Integral Constant Expression.
A non-const object (like n1) cannot appear anywhere in an Integral Constant Expression.
Have you considered using std::vector<int>?
[Note--The cast is entirely unnecessary. Both of the following are both exactly the same:
const int N = n1;
const int N = const_cast<const int&>(n1);
--End Note]
Only fixed-size arrays can be allocated that way. Either allocate memory dynamically (int* foo = new int[N];) and delete it when you're done, or (preferably) use std::vector<int> instead.
(Edit: GCC accepts that as an extension, but it's not part of the C++ standard.)

Understand Reference and Dereferencing Operators?

Can someone please help me understand Reference and Dereference Operators?
Here is what I read/understand so far:
int myNum = 30;
int a = &myNum; // a equals the address where myNum is storing 30,
int *a = &myNum; // *a equals the value of myNum.
When I saw the code below I was confused:
void myFunc(int &c) // Don't understand this. shouldn't this be int *c?
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum);
cout<< myNum ;
}
int &c has the address to what's being passed in right? It's not the value of what's being passed in.
So when I do c+=10 it's going to add 10 to the memory address and not the value 30. Is that correct?
BUT... when I run this...of course with all the correct includes and stuff...it works. it prints 40.
Actually the ampersand in the function parameter list for myFunc is not an address operator, nor a bitwise and operator. It is a reference indicator. It means that within myFunc, the parameter c will be an alias of whatever argument is passed to it.
You have a few issues here.
your second line of code int a = &myNum; // a equals the address where myNum is storing 30 is wrong;
you can combine it with line 3 like so:
int *a = &myNum; // a equals the address where myNum is stored;
*a == myNum.
The type int & is read as "reference-to-int". Perhaps the Wikipedia article can help you understand what this means.
Both pieces of code are valid and your understanding of pointers in the first piece of code is correct. However, the ampersand (&) in the two pieces of code are actually different things. (Like how * is both the dereference and multiplication operator)
The second piece of code shows how the & can be used to pass variables to a function by reference. Normally if you had code like this:
int a;
void foo(int bar) {
bar = 3;
}
int main() {
a = 5;
foo(a);
// a still equals 5
}
The call to 'foo()' does not affect the variable you passed to it (bar or in this case, a). However if you changed this line:
void foo(int bar) {
to
void foo(int &bar) {
then it would affect the variable and at the end of the program above, the value of a would be 3.
In C++ when you pass things by reference using int &c you don't need to dereference. You only need to dereference pointers. If it was int *c then it would be necessary. Just remember in both cases you change the value of what was passed in the original caller so myNum is now 40.
Let's have a look at the assumptions first:
int myNum = 30;
// this won't compile. &myNum is the address of an int (an int *), not an int:
int a = &myNum;
// *a is a pointer to an int. It received the address of myNum (which is &myNum),
// and not its value
int *a = &myNum;
About the code:
void myFunc(int &c)
// c is passed by reference. This is a kind of "hidden pointer" that
// allows using the variable as if it was not a pointer but the pointed variable.
// But as this reference and the variable that was passed by the caller (myNum
// in your example) share the same address (this is the property of a reference),
// any modification of the value of c inside myFunc modifies it in the
// caller's scope too (so here, it modifies myNum).
{
c += 10;
cout<< c;
}
int main()
{
int myNum = 30;
myFunc(myNum); // displays 40
// What follows displays 40 as well, due to the fact
// c was passed by reference to myFunc that added 10 to it
cout<< myNum ;
}
So when I do c+=10 it's going to add 10 to the memory address and not
the value 30. Is that correct?
No, 10 was added to the value of c by myFunc.
As c is a reference (a "hidden pointer to") that received myNum, myNum was modified as well.