-1

I am having confusion with the return value of post-increment and pre-increment operator.Whether it returns r-value or l-value.

    #include<iostream>
    using namespace std;
    int main(){
        int a=10;
        cout<<++a++<<"\n";
    }

The following code give a compile error.

error: lvalue required as increment operator

Why is there an error?

How does the compiler evaluates the expression ++a++?

Bathsheba
  • 231,907
  • 34
  • 361
  • 483

4 Answers4

8

The result of the post-increment expression, a++ is an rvalue; a temporary with the value that a had before incrementing. As an rvalue, you can use its value, but you can't modify it. Specifically, you can't apply pre-increment it, as the compiler says.

If you were to change the precedence to do the pre-increment first:

(++a)++

then this would compile: the result of pre-increment is an lvalue denoting the object that's been modified. However, this might have undefined behaviour; I'm not sure whether the two modifications and the various uses of the value are sequenced.

Summary: don't try to write tricky expressions with multiple side-effects.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • I'm pretty sure your semi-guess is correct, and the two increments are not sequenced, so the result would be undefined behavior (it certainly was in C++98/03, and while the new sequencing rules have made *some* things defined that didn't used to be, I don't think this is one of them). – Jerry Coffin May 13 '15 at 16:23
6

Conceptually, the postfix ++ has higher precedence than prefix ++.

So a++ will be computed first. But this is not an lvalue (as it's the previous value of a). It therefore cannot be pre-incremented. Hence the compiler output.

More importantly though, the behaviour of the whole expression ++a++ is undefined due to their being no sequencing point in the expression.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

Just for what it's worth (not much, IMO) if you make the a in question the proper type, it's possible to get this to compile and have defined behavior. The trick (and in this case it's a dirty, evil trick) is to overload the post-fix increment operator to return an lvalue:

class dirty_evil_trick {
    int val;
public:
    dirty_evil_trick() : val(0) {}

    // to demonstrate, I'll just make postfix increment act like prefix increment.
    dirty_evil_trick operator++(int) {  
        ++val;
        return *this;
    }

    dirty_evil_trick operator++() { 
        ++val;
        return *this;
    }

    operator int(){ return val; }
};

As implied by the name, this is (at least in my opinion) truly horrible code. We've made both the prefix and postfix increment operators act like prefix increment. So, for example, if we exercise it as follows:

int main(){ 
    dirty_evil_trick a;
    std::cout << ++a++;
}

...it should print out 2. And, since invoking the operator overload functions imposes ordering constraints, we should be able to count on that result with all conforming compilers.

I'll repeat once more though: this is not intended as advice about how you should write code. It's really just a demonstration of what the error message you got meant, and how you can write code that does let this actually work (or, at least compile and do something. Whether that qualifies as "working" is a whole 'nother question).

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
0

First of all, that's terrible programming style. Depending on your needs, you can easily write:

++a;
cout << a++ <<"\n";

or

a++;
cout << ++a <<"\n";

Coming to the compiler error...

Due to operator precedence, ++a++ is the same as ++(a++). However, a++ evaluates to an rvalue. Using the prefix increment operator on an rvalue is not allowed. That will be analogous to using ++10, which is not legal.

R Sahu
  • 204,454
  • 14
  • 159
  • 270