8

I have just learned that the result of the prefix increment operator in C++ is an lvalue. There are probably cases where this behavior helps the programmer be more effective, but I could not think of any. What are some idiomatic uses of this behavior of the prefix increment operator?

AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68
  • Can you please be more elaborate...as to in what context you are measuring efficiency. – ravi Dec 15 '14 at 15:17
  • See also: http://stackoverflow.com/a/371669/567292 – ecatmur Dec 15 '14 at 15:43
  • Thank you. I missed that post in my research before posting the question. By effectiveness I mean concise and clear code that would not be such had the feature not been present in the language. – AlwaysLearning Dec 15 '14 at 16:19
  • possible duplicate of [Why is ++i considered an l-value, but i++ is not?](http://stackoverflow.com/questions/371503/why-is-i-considered-an-l-value-but-i-is-not) – Heath Hunnicutt Dec 22 '14 at 17:39

3 Answers3

6

The reason prefix ++ returns an lvalue is orthogonality; I've not seen any use for it that wouldn't qualify as obfuscation. But the question is: what rules apply to cause an expression to be an lvalue. In C, the basic rule is that expressions which modify one of their operands aren't lvalues, but a number of people wanted to support things like:

T&
someFunction( T& lhs, T const& rhs )
{
    //  ...
    return lhs = rhs;
}

This works for user defined types (because operator= will be a member function), and some members wanted to support it for built-in types as well. So the basic rule became: if an operator required an lvalue operand, which it modified, and the results of the operator were the changed operand, then it is an lvalue. (Thus, while prefix ++ is an lvalue, postfix isn't, because the results of the expression aren't the changed operand.)

Personally, I'm not sure I agree. I have no problem with replacing the above with:

T&
someFunction( T& lhs, T const& rhs )
{
    //  ...
    lhs = rhs;
    return lhs;
}

which is how I'd write it in my own code. But given that the first example is legal for user defined types (where operator= returns a T&), and that a number of committee members did like it, it seems logical to extend it to the built-in types, and the resulting rule is coherent, even if no one ever actually has the occasion to use the results of prefix ++ as an lvalue.

EDIT:

Just to make it clear: I asked this very question at one of the meetings (when we were defining C++ 98), and this was the response I got (from, if I recall correctly, Andy Koenig, who worked with Stroustrup on the earliest implementations of C++). It was also the justification for having the default implementation of operator= return a T& rather than a T const&.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
4

The change from C where ++x is an rvalue to C++ where ++x for built-in types is an lvalue is probably because there are much more useful applications. For example, you might define a function alternatively as

void f (int x);
void f (int& x); 

and the fact that ++x is an lvalue allows you to call f (++x); in either case. In C, only the first case was legal, and works just fine with an rvalue. In C++, you want an lvalue.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • I think a case with `int f(int x);` and `int& f(int& x);` would be a bit clearer of an example. By returning an lvalue when given an lvalue, the argument's lvalue-ness is preserved through the function, instead of everything being forced to an rvalue. So it would be surprising if feeding `++x` to the function suddenly called the rvalue version of the function instead. – Mike DeSimone Dec 15 '14 at 15:37
  • 1
    The clearest example would be `int const& f(int const&)` and `int& f(int&`)`. But this leads to `f(i++)` calling the first, and `f(++i)` the second, which is more of an argument for _not_ making prefix `++` an lvalue. – James Kanze Dec 15 '14 at 16:10
0
i=9;
j=10;
k = ((i)>(j))?(j):(++i);

In the above case we have a use of prefix increment operator as you can c we first check i>j which will be false in this case then we are assigning the value ++i to k which will give us k=1. Here in one single statement we have used i twice but once the value was 9 and other time the value was 10. If you try to achieve this without prefix increment operator we would have to use another temporary variable to store to the value of i then increment i to assign to k. Without using prefix operator

  i=9;
 j=10;
Temp=i;
 i=i+1;
k = ((Temp)>(j))?(j):(i);

Still if we arrive at a conditin where temp is greter than j then we will have the value of i incremented even if we dont use it. Using prefix operator tje value of i will only increment if i less than j.

varun
  • 1,473
  • 1
  • 9
  • 15
  • 1
    The OP asked about the use of ++i as an lvalue. Your first code is just as fine in C, where ++i is _not_ an lvalue. – gnasher729 Dec 15 '14 at 15:25