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;
}
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()++;
}
Take the following code, where a function returns by reference:
#include <cstdio>
using namespace std;
int & myFunction(int & input) {
return input;
}
int main() {
int x;
int y = 10;
x = myFunction(y);
printf("x is %d\n",x); // x is 10
printf("y is %d\n",y); // y is 10
x = 20;
printf("x is %d\n",x); // x is 20
printf("y is %d\n",y); // y is 10
return 0;
}
Except the obvious pitfall of returning a reference to a local variable of the function (which is not the case here), are there any things to watch out for in this kind of setup? In other words, is there anything "more" to this code than a function which simply returns things by reference in order to avoid unnecessary copying operations?
Except the obvious pitfall of returning a reference to a local
variable of the function (which is not the case here), are there any
things to watch out for in this kind of setup?
No, not really, it's perfectly valid but it has no advantage either. (in the current state of myFunction)
in order to avoid unnecessary copying operations?
There's still a copy being made here:
int x;
int y = 10;
x = myFunction(y); // value of y is copied to x.
This is less readable and doesn't speed up anything when it comes to just normal initialization:
int x;
int y = 10;
x = y;
There's no reason to do this in this situation, just stick to normal initialization.
Of course, if myFunction adds some kind of modification to a more complex object than int& then you can take advantage of returning the reference as you can then:
chain.method().calls();
The code you provided works because you're passing the variable to your function by reference, and still returning it by reference. This is consistent and works, but is weird. Why would you return the same variable that you're passing by reference? (I just remembered from the comments that this is useful for chaining in std::ostream, for example.)
On the other hand, if you pass that variable by value, you'll have a dangling reference and it won't work. So this won't work:
int & myFunction(int input) {
return input;
}
In my opinion, the only return by reference I find appropriate is if you return a variable from inside a class's method. Besides that, I don't think you should return by reference at all.
You can catch a variable as a constant reference and avoid copying it if you want without having a dangling if you do this:
int myFunction(int input) {
return input;
}
int main()
{
const int& myInt = myFunction();
//myInt is still valid here
}
This is a special case that.
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.
I had a simple question and was hoping for the underlying logic behind passing by reference.
Here's one code (let's call it Code1):
void fn(int& a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here's another code (Code2):
void fn(int* ptr)
{
*ptr = 6;
}
int main()
{
int b = 5;
fn(&b);
cout << b;
}
And a pass by value code (Code 3):
void fn(int a)
{
a = 6;
}
int main()
{
int b = 5;
fn(b);
cout << b;
}
Here goes my question. Intuitively, I see that while passing by value (Code3), the values are copied ie a would just have taken/copied into itself the value of b. Thus, as a general rule, I see that value passed is just copied always to the called function (here fn). Even with the pointer code (ie Code2), the first line of Code 2 ensures that int *ptr = &a;
I don't understand how this would work in Code1. Saying that &a = b makes no sense. Is this an exception, or does this fit into a rule that is consistent with the cases discussed in the paragraph above?
Thanks!
In this function:
void fn(int &a) {
a=6;
}
the term "&a" does not mean "the address of the variable a". It means "a reference called a". Code 1 and Code 2 are effectively the same (but note that the function in Code 2 can be passed an invalid pointer, which is (almost) impossible for Code 1).
For most intents and purposes, a reference is just a pointer in disguise. Different syntax, same effect (mostly).
Conceptually, in your first case what happens is that the same variable has two labels: b, visible within the scope of main(); and a, visible within the scope of fn.
You don't have to worry about what the compiler does "behind the scenes" to implement this concept.
If you mentally promote the compiler's "behind the scenes" actions to actually being imagined principles of C++, e.g. "the reference is a pointer in disguise", then it leads you to get confused about what is actually a pretty simple concept: the ability to give multiple names to a variable.
It is nothing special being a function parameter; e.g. you could write in main():
int a;
int &c = a;
which is exactly equivalent to:
int c;
int &a = c;
In both cases there is an int variable with two labels, a and c.
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