4

I have the given code, which gets an error:

error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int' const int b = f(a++); ^

int f(int& a) { return a; } int main() { // your code goes here int a = 5; int b = f(a++); std::cout << b << std::endl; return 0; } 

What the cause of this error ?

2
  • does it compile without post-increment? Commented Apr 21, 2015 at 13:25
  • 1
    Does it work if you change to the pre version: int b = f(++a);? the problem could be that the postfix version returns a temporary object Commented Apr 21, 2015 at 13:26

3 Answers 3

5

You can't bind a temporary to a non-const reference.

Post-increment (a++) increments a and returns a temporary with a's old value.

Why are you passing by non-const reference? - it doesn't look like you're changing the parameter inside the function, just just pass by value or const reference.

If you were changing the parameter, what would you expect the behavior to be, considering a++ already changes it? Would the change be intuitive? Legal?

Sign up to request clarification or add additional context in comments.

Comments

1

The postfix increment operator on an int returns a temporary value. A temporary value cannot bind to a non-const lvalue reference, because modifying that temporary doesn't make sense. You are trying to bind the temporary to an int&, which is giving an error.

To fix this, either use the pre-increment operator (++a), or take your argument by value (it's better to pass builtin types as value rather than const T&):

int f(int a) { return a; } 

Comments

1

This function:

int f(int& a) 

accepts non-const reference. Such references must always point to a valid objects, residing at certain memory locations (*).

Post incrementation works as follows:

 - save current value as `r` - increment original variable - return `r` 

That's because result of post-incrementation is a temporary, yielding value from before incrementation. Such temporary must be passed either as value or const reference:

int f(int a) //This will work int f(const int& a) //And this 

(*) In fact, older compilers allowed for such constrcuts. For example, this code will compile under VC6:

struct T {}; void f(T& t) { } int main() { f(T()); } 

However, such behaviour is not standard-compliant.

Comments