int a = 0; auto && b = ++a; ++a; cout << a << b << endl;
int a = 0; auto && b = a++; ++a; cout << a << b << endl;
Why in first example
++a in 3rd line also increments
b, and why there is no such behavior in second example?
Update: New question arised.
Because pre-increment (
++a) first increments the value of
a, stores the result, and then returns the reference to
b effectively point to the same object.
a++), however, first stores the current value of
a in a temporary, increments
a, and returns this temporary - to which your rvalue ref points.
b point to different objects, more specifically -
b is a temporary holding the value of
a prior to incrementing.
This is the reason why it's encouraged to use
it++ for iterators and other complex objects that define increment / decrement: the latter creates a temporary copy and thus may be slower.
The difference is that
++a is an lvalue, however
a++ is not. This is specified by C++14 [expr.pre.incr]/1:
The operand of prefix
++is modified by adding 1 [...] The operand shall be a modifiable lvalue. [...] The result is the updated operand; it is an lvalue
[...] The result is a prvalue.
Now we consider
auto && b = ++a; .
++a is an lvalue.
auto&& is a forwarding reference. Forwarding references can actually bind to lvalues: the
auto may itself deduce to a reference type. This code deduces to
int &b = ++a;.
When a reference is bound to an lvalue of the same type, the reference binds directly, so
b becomes another name for
In the second example,
auto && b = a++;,
a++ is a prvalue. This means it doesn't have an associated address and it's no longer any relation to the variable
a. This line has the same behaviour as
++a; auto && b = (a + 0); would.
a++ is a prvalue,
auto&& deduces to
auto deduces to
int). When a reference of non-class type is bound to a prvalue, a temporary object is copy-initialized from the value. This object has its lifetime extended to match the reference.
b in the second case is bound to a different object from
a, a "temporary" int (which is not really so temporary, since it lasts as long as
The reference binding rules are in [dcl.init.ref].
In the second case (post-increment) b actually references the temporary created for (a++), so the increments do not affect b.