-1

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

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
soul
  • 37
  • 5

6 Answers6

1

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.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

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...

Amit
  • 45,440
  • 9
  • 78
  • 110
0

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
}
bpgeck
  • 1,592
  • 1
  • 14
  • 32
  • actually this is a question of George Summers Technical MCQs book and the answer given is 322 – soul Aug 15 '15 at 18:53
  • -1: This answer is wrong. This code is passing a pointer (and the address of `a`). The OP is passing by reference. `Type&` and `&expression` are two different things. – Lightness Races in Orbit Aug 15 '15 at 19:16
0

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.

Luke Xu
  • 2,302
  • 3
  • 19
  • 43
  • There are no "constants" here. No idea why you think there are. – Lightness Races in Orbit Aug 15 '15 at 19:17
  • @LightnessRacesinOrbit There absolutely are constants... Not only are you incorrect but my post above solves his problem. He's returning an rvalue not an lvalue. – Luke Xu Aug 15 '15 at 19:20
  • Show me one constant. The initialisers `0` and `5`, which you were not referring to, do not count. – Lightness Races in Orbit Aug 15 '15 at 19:25
  • Then read _my_ answer. – Lightness Races in Orbit Aug 15 '15 at 19:25
  • @LightnessRacesinOrbit int a(int m) returns a constant. Ask your self this. Can this be on both sides of an '=' sign or only the right side? If the answer is 'the right side' then it is not a variable with a memory address. Hence a constant which can ONLY be assigned. – Luke Xu Aug 15 '15 at 19:28
  • @LightnessRacesinOrbit Have you tried compiling *your answer* because it gives the exact same error... – Luke Xu Aug 15 '15 at 19:31
  • You do not appear to understand what "constant" means. `int a(int m)` does not return a constant. At all. As for your "assignment" logic, er, no, that's because built-in assignment cannot have an rvalue on the LHS. It's got nothing whatsoever to do with being "constant". – Lightness Races in Orbit Aug 15 '15 at 19:34
  • @LightnessRacesinOrbit Why are you telling me when I don't know what I'm talking about when your solution is giving the exact same compilation error as OP's and mine solves the problem? Besides if it doesn't return a constant, inform me on what it DOES return? – Luke Xu Aug 15 '15 at 19:37
  • I just did. I told you what it does return, and I told you why the error in my answer was unrelated to this discussion, and I fixed it. Calm down. – Lightness Races in Orbit Aug 15 '15 at 19:43
  • Here's an example showing that your notion of the return value being a "constant" is pure fantasy: http://coliru.stacked-crooked.com/a/2fe4face984028eb – Lightness Races in Orbit Aug 15 '15 at 19:46
0

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.

0

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;
}
gen-y-s
  • 871
  • 6
  • 12