I was searching for explanations over reference variables in c++ and I found this:
#include<iostream>
int a=10; //global 'a' so that fun doesn't return a reference of its local variable
int & fun();
int main()
{
int p = fun(); //line to be noted
std::cout << p;
return 0;
}
int & fun()
{
return a;
}
This worked and so does this:
#include<iostream>
int a=10; //global 'a' so that fun doesn't return a reference of its local variable
int & fun();
int main()
{
int &p = fun(); //line to be noted
std::cout << p;
return 0;
}
int & fun()
{
return a;
}
My question is how could an integer variable store the value of reference as is being done in first code snippet [line number 6]. Isn't the correct syntax as depicted in code snippet 2 [at line 6], i.e. we should define a reference variable (int &p) to carry the reference and not a regular integral variable?
Shouldn't the compiler give an error or at least a warning? I am using GCC 4.7.1 64-bit.
Okay got it ... #chris : you were right..When I did this:
int p = fun();
p++;
std::cout << p << endl << a;
It showed the results to be 11 and 10. Hence only a's value is copied into p and p doesn't became the alias of a.
But when I tried the same with second code, it showed values of both a and p to be 11. Hence p became the alias of a.
No, it is fine either way.
The return value reference is not even necessary in this special case because you are not trying to modify the return value "on the fly" or the 'a' later, like when you use arithmetic operator overloads for that purpose, for instance
Related
Just started learning c++ and came across this example where the function is returning a reference to a local static variable.
int& fun() {
static int x = 10;
return x;
}
int main() {
int &z = fun();
cout << fun() << " ";
z = 30;
cout << fun();
return 0;
}
What does the line int &z = fun(); do? Are we storing a reference inside another reference? I'm new to the language and all I know is that reference variables refer to a variable just like an alias. Can anyone explain how this works?
Are we storing a reference inside another reference?
No, references aren't even required to have "storage". A reference is something to simplify programming. auto& thing = foo.get_value_reference(); and then using thing makes code easier to write and debug. thing doesn't even have to exist as a separate entity when you look at the final assembly code.
int orig;
int& a = orig;
int& b = a;
b is now a reference to orig - nothing else. You can't reference a reference.
Are we storing a reference inside another reference?
No, there is no reference to reference, at least in C\C++.
For me, a reference is just a different name for another variable, at the end, they are all referring to the same, single object. In more detail, abstractly, whenever you write int& a = b, all you have is still b, and there is no such thing called a, that ever exist. (a is just an alias of b)
Because of that, we can't have a different name of a name, that would sound a bit weird, since it does not actually refer to anything that exist.
In your case above, what int& fun() does is returning the actual static int x = 10;. And int &z = fun();, once again, refer directly the the actual static int x = 10;. Whatever z or anything, afterall, it is just static int x = 10, under different names.
This would be different if you remove the amphersand-& to int fun(), which returns a copied version of int x = 10;, which means now existed two different things: int x = 10 and a copy of int x = 10.
That's why C\C++ is memory-efficient, isn't it? You know when things get copied and when it does not, which helps optimization a lot!
Hope this helps!
First of all, a variable declared static inside a function is allocated when the program begins and deallocated when the program ends. Unlike normal local variables, it is safe to keep a reference to a static variable after returning from the function in which it is declared. It continues to exist and will keep its value.
Let's consider this function:
int& fun() {
static int x = 10;
return x;
}
Returning a reference to the static variable x is like returning the variable itself. We can increment the variable through that reference, for instance:
cout << fun()++ << endl;
cout << fun()++ << endl; // output: 11
cout << fun() << endl; // output: 12
This would not be possible if fun() returned the value of x (the integer 10) instead of a reference to variable x itself (whose value we can update).
int &z = fun() lets us refer to that same static variable through the name z in the same way:
int &z = fun();
cout << z++ << endl;
cout << z++ << endl; // output: 11
cout << z++ << endl; // output: 12
cout << fun() << endl; // output: 13
Both the function return type and z have to be references for the above to work.
If z were not a reference but an int z variable, we would be making a copy of the original value and incrementing that in place of the static variable x itself.
If the function return type were a value (instead of a reference), it would return the value of x, not a reference to x itself. In this case, int f(); int &z = f(); would try to take a reference to the temporary return value of the function. In fact, this code doesn't even compile.
Functions that return static variables (by reference or otherwise) have their uses. One of which is that a static variable inside a function is initialized at runtime, the first time we run through its declaration.
In the code below, init_x() is called when initializing the static variable x. This happens the first time fun() is called to retrieve the value of x.
int& fun() {
static int x = init_x();
return x;
}
int main() {
do_other_stuff();
fun()++; // init_x() is called here
fun()++;
fun()++;
}
I know this is already a commonly asked question, but I'm more curious about how pointers and references behave at a lower level (like how compiler deals with them, and how they look like in memory), and I didn't find a solution, so here I am.
At first I was wondering if an array can be passed as a parameter without being cast (or decay) into a pointer. More specifically. I would like the following code:
void func(?? arr) {
cout << sizeof(arr) << "\n";
}
int main() {
int arr[4];
func(arr);
return 0;
}
to output 16 instead of 8, which is the size of a pointer.
First I tried
void func(int arr[4]);
Hoping that specifying the size can keep the property of an array, but arr is still treated as a pointer.
Then I found something that worked:
void func(int (&arr)[4]);
But it confused me.
In the past I was under the impression that although pointers and references had different meanings, they had the same behavior when the code was actually executed.
I got that idea from my own experiments:
void swap(int* a, int* b) {
int c = *a;
*a = *b;
*b = c;
}
int main() {
int a = 3, b = 5;
swap(&a, &b);
}
and
void swap(int& a, int& b) {
int c = a;
a = b;
b = c;
}
int main() {
int a = 3, b = 5;
swap(a, b);
}
were compiled into the same assembly code, and so did
int main() {
int a = 3;
int& b = a;
b = 127;
return 0;
}
and
int main() {
int a = 3;
int* b = &a;
*b = 127;
return 0;
}
I turned off optimization and both g++ and clang++ showed this result.
Also my thought on the first experiment:
when thinking in terms of memory, swap should have its own stack frame and local variables. Having a in swap directly mapped to the a in main didn't make much sense to me. It was as if the a in main magically appeared in the stack frame of swap, where it shouldn't belong. So it didn't surprise me that it got compiled into the same assembly as the pointer version. Maybe the magic of reference was achieved by a pointer underneath the hood. But now I'm not sure.
So how does a compiler handle references and how do references look like in memory? Are they variable that occupies space? And how can I explain the result of my experiments and the array problem?
The old C idiom is, that arrays get turned into pointers to the array type, when a function is called. And that is mostly still true für C++.
So for the details of it, let's look at two functions taking an integer argument, first:
void f(int x) { x = 42; } // function called with x by value
void g(int& x) { x = 42; } // function called with x by reference
As f() is called by value, a copy of the argument is made, and the assignment x = 42; inside the function has effectively no effect for the caller of the function. But for g(), the assignment of x becomes visible to the caller:
int a = 0, b = 0; // initialize both a and b to zero
f(a); // a is not changed, because f is called by value
g(b); // b is changed, because g is called by reference
std::cout << a << " " << b << std::endl; // prints 0 42
For arrays, the same rules should hold, but don't. So let's try it:
void farr(int x[4]) { x[0] = 42; } // hypothetical call by value
void garr(int (&x)[4]) { x[0] = 42; } // call by reference
And let's call these functions:
int c[4] = { 1, 2, 3, 4 }, d[4] = { 5, 6, 7, 8 };
farr(c); // call by value?
garr(d); // call by reference
for(unsigned i = 0; i < 4; i++)
std::cout << c[i] << (i < 3 ? ", " : "\n");
for(unsigned i = 0; i < 4; i++)
std::cout << d[i] << (i < 3 ? ", " : "\n");
The unexpected result is, that the farr() function (unlike the f function before) does modify its array, too. The reason is an old C idiom: Because arrays must not be copied directly by assignment, functions cannot be called with arrays by value. Therefore array declarations in parameter lists are automatically converted into a pointer to the first element of the array. So the following four function declarations are syntactically identical in C:
void farr1(int a[]) {}
void farr2(int a[4]) {}
void farr3(int a[40]) {}
void farr4(int *a) {}
Being compatible with C, C++ took over that property. So it is not a syntactical error (but likely causes undefined behaviour!) to call farr2() or farr3() with an array of different size. Furthermore, though, references come in in C++. And yes, as you already suspected, a reference to an array is internally represented as a pointer to the first array element. But, and that is the advantage of C++: If you call a function, that expects a reference to an array (and not just an array or a pointer), the size of array is actually validated!
So, calling farr() with an int-Array of size 5 is possible, calling garr() with the same leads to an compiler error. That gives you better type checking, so you should use it, whereever possible. And it even allows you to pass the array size to a function by using a template:
template<std::size_t N>
void harr(int (&x)[N]) { for(std::size_t i = 0; i < N; i++) x[i] = i*i; }
the output of the code is 30.But I am not sure how it is getting to it.
#include <iostream>
int &fun()
{
static int x = 10;
return x;
}
int main()
{
fun() = 30;
std::cout << fun();
return 0;
}
I am expecting that the output will be 10 but its showing 30. how?
Your fun gives a location of an int (since it returns a reference). That location is the static variable x which is initialized (once, conceptually before the program runs) to 10.
Then fun() = 30; is assigning that location. So x gets assigned to 30.
At last cout << fun() displays the content of that location.
If x was some automatic variable your code would have undefined behavior.
PS. A crude way of thinking about & unary reference like int &r = x; is that it sort-of "transforms" your code as: introduce a phantom pointer int *p = &x; (where p is some fresh variable not appearing elsewhere) and replace r with *p, so &r with p, everywhere in the scope of that r.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
The code snippet is as follows
#include <iostream>
using namespace std;
int a(int m)
{
return ++m;
}
int b(int &m)
{
return ++m;
}
int c(int &m)
{
return ++m;
}
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
q+=b(a(q));
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}
The error occurring is invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int' at q+=b(a(q)). How to go about the error so that this program prints a desired output
Timothy J Williams is one or both of the following things:
wrong;
teaching C++ as it pertains to Visual Studio only, without disclaiming it, which is ill-advised.
References cannot bind to temporaries. It is not allowed in C++. Visual Studio allows it as a non-standard extension, but that's it. Some people get confused and think that means it's valid C++. It's not.
You will have to store the results of function calls like b(1) into named variables before you pass them anywhere by reference.
int main()
{
int p = 0, q = 0, r = 0;
int result_of_b_p = b(p);
p += a(result_of_b_p);
int result_of_a_q = a(q);
q += b(result_of_a_q);
int result_of_c_r = c(r);
r += a(result_of_c_r);
std::cout << p << q << r << '\n';
}
I should also note that the cited code is confusing and appears to serve no purpose other than for contrived "test your knowledge" challenges. I'd pay not too much attention to this and instead learn C++ from a proper book. After all, Timothy Williams claims that the above program outputs 322; it doesn't.
You cannot pass by reference a constant.
To break down your code.
int a(int m){
return ++m;
}
This will return an int (constant, eg. 5)
Then in
int b(int &m){
return ++m;
}
You are now technically passing in an integer (constant) not a variable into B. You must pass B in as a variable.
Try exactly what you have but passing in
int x = a(your_number_here);
int z = b(x);
EDIT:
int main(void){
int p=0,q=0;
int x = 5;
p = a(x);
q = b(p);
cout << q << endl;
return 0;
}
Returns 7.
The error is a result of trying to call a function that takes a reference with a value. It would be like calling b with a value literal b(1). That can't work...
The function call is where you pass by reference. See below:
void foo (int* m)
{
(*m)++;
}
int main (void)
{
int a = 0;
foo (&a);
cout << a << endl; // prints 1
}
So here b(int& m) takes a reference to an integer. Think about it this way. A reference is a "safe pointer" for which the compiler automatically handles the dereferencing operations.
The return value of a(int m) is a temporary, i.e. it is a temporary value that goes out of scope as soon as the function returns and its value has been utilized in some way. So you can do x = a(15); and x will become a copy of the returned 16. This is what an r-value is. A sort of "temporary" (r because it is on the right side of the expression). So when you have a pointer to a temporary value it does not make sense in most cases. For example in the following code
int* return_local() {
int a = 10;
return &a;
}
This will give you a compiler warning. Because you don't want to bind a pointer to a value which will go out of scope. Similarly you don't want a reference to an object that will go out of scope as soon as the function has returned and its value has been utilized. That is why there is an error in your code. a(int m) returns an r-value and when you do b(a(q) you are trying to bind a reference to an r-value
Now there is something called an r-value reference which takes the form void some_func(int&& rvalue_reference) in syntax. The && means r-value reference not reference to reference. Look it up if you are interested.
It's not allowed to pass a r-value as a non-const reference argument. This happens in the line whereyou call the function b with a(q) as its argument, which is an r-value (an expression which is not a simple variable).
So you need to first call a and store itsvalue in a variable, and then pass this variable to b:
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
int t=a(q);
q+=b(t);
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}
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.