12

Why does pre-increment work but post-increment does not on a reference variable?

#include <iostream>

void swap(int&, int&);

int main()
{
    int x=10, y=20;
    int &a=x, &b=y;
    swap(++a, ++b);  //swap (a++,b++) is not allowed.
    printf("%d %d ", a, b);
    return 0;
}

void swap(int& x, int& y)
{
    x+=2;
    y+=3;
} 

Why is swap(++a, ++b) allowed but swap(a++, b++) says:

[Error] invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int'

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
Renuka
  • 141
  • 1
  • 6
  • For simplicity's sake, note that the same behaviour occurs if you try to use `main`'s `x` and `y` directly. References `a` and `b` only serve to make the problem appear more complicated than it is. – Christian Hackl Oct 02 '15 at 16:17

4 Answers4

14

When you call

swap (a++,b++)

a++ and b++ give you a temporary object since post incrementing returns the previous values. Since swap() takes its parameters by reference they cannot bind to those temporary values. using ++a and ++b work as we first increment a and b and then pass it to swap so there is no temporary.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
2

++a returns an l-value but a++ returns an r-value. You need to pass an l-value to the swap() function.

Relevant post on l-valu and r-value: postfix (prefix) increment, L-value and R-value (in C and C++)

Community
  • 1
  • 1
Lorenzo Belli
  • 1,767
  • 4
  • 25
  • 46
2

The function std::swap must swap the value of two variable, aka a lvalue reference. The expression x++ is not a variable, but a value, or a rvalue. A rvalue cannot be bound to a lvalue reference.

The difference between a rvalue and a lvalue could be explained that way:

int p;
/* p is left value, 3 is right value, ok */
p = 3;

But the following is not valid:

/* not ok, 3 is right value */
3 = p;

What you are sending to std::swap are two value of numbers.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
1

Passing l-value / variable:

int x = 5, y = 9;
swap(x, y); // allowed bcos x and y are l-values / variables

pre-increment (also pre-decrement):

int x = 5, y = 9;
swap(++x, ++y); // allowed bcos ++x and ++y are l-values

Passing r-value / value:

swap(5, 9); // NOT allowed bcos 5 and 9 are values (NOT variables)

post-increment (also post-decrement):

int x = 5, y = 9;
swap(x++, y++); // NOT allowed bcos x++ and y++ are r-values
SridharKritha
  • 8,481
  • 2
  • 52
  • 43