Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Well as another answerer pointed out already the reason why <code>++i</code> is an lvalue is to pass it to a reference.</p> <pre><code>int v = 0; int const &amp; rcv = ++v; // would work if ++v is an rvalue too int &amp; rv = ++v; // would not work if ++v is an rvalue </code></pre> <p>The reason for the second rule is to allow to initialize a reference using a literal, when the reference is a reference to const:</p> <pre><code>void taking_refc(int const&amp; v); taking_refc(10); // valid, 10 is an rvalue though! </code></pre> <p>Why do we introduce an rvalue at all you may ask. Well, these terms come up when building the language rules for these two situations:</p> <ul> <li>We want to have a locator value. That will represent a location which contains a value that can be read. </li> <li>We want to represent the value of an expression. </li> </ul> <p>The above two points are taken from the C99 Standard which includes this nice footnote quite helpful:</p> <blockquote> <p>[ The name ‘‘lvalue’’ comes originally from the assignment expression E1 = E2, in which the left operand E1 is required to be a (modifiable) lvalue. It is perhaps better considered as representing an object ‘‘locator value’’. What is sometimes called ‘‘rvalue’’ is in this International Standard described as the ‘‘value of an expression’’. ]</p> </blockquote> <p>The locator value is called <em>lvalue</em>, while the value resulting from evaluating that location is called <em>rvalue</em>. That's right according also to the C++ Standard (talking about the lvalue-to-rvalue conversion):</p> <blockquote> <p>4.1/2: The value contained in the object indicated by the lvalue is the rvalue result.</p> </blockquote> <h3>Conclusion</h3> <p>Using the above semantics, it is clear now why <code>i++</code> is no lvalue but an rvalue. Because the expression returned is not located in <code>i</code> anymore (it's incremented!), it is just the value that can be of interest. Modifying that value returned by <code>i++</code> would make not sense, because we don't have a location from which we could read that value again. And so the Standard says it is an rvalue, and it thus can only bind to a reference-to-const. </p> <p>However, in constrast, the expression returned by <code>++i</code> is the location (lvalue) of <code>i</code>. Provoking an lvalue-to-rvalue conversion, like in <code>int a = ++i;</code> will read the value out of it. Alternatively, we can make a reference point to it, and read out the value later: <code>int &amp;a = ++i;</code>. </p> <p>Note also the other occasions where rvalues are generated. For example, all temporaries are rvalues, the result of binary/unary + and minus and all return value expressions that are not references. All those expressions are not located in an named object, but carry rather values only. Those values can of course be backed up by objects that are not constant. </p> <p>The next C++ Version will include so-called <code>rvalue references</code> that, even though they point to nonconst, can bind to an rvalue. The rationale is to be able to "steal" away resources from those anonymous objects, and avoid copies doing that. Assuming a class-type that has overloaded prefix ++ (returning <code>Object&amp;</code>) and postfix ++ (returning <code>Object</code>), the following would cause a copy first, and for the second case it will steal the resources from the rvalue:</p> <pre><code>Object o1(++a); // lvalue =&gt; can't steal. It will deep copy. Object o2(a++); // rvalue =&gt; steal resources (like just swapping pointers) </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload