Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is an example of a difference in allowed usage or behavior between an xvalue and a prvalue FOR NON-POD objects?
    primarykey
    data
    text
    <p><a href="https://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues">What are rvalues, lvalues, xvalues, glvalues, and prvalues?</a> gives a good overview of the taxonomy of rvalues/lvalues, and one of the recent answers to that question (<a href="https://stackoverflow.com/a/9552880/368896">https://stackoverflow.com/a/9552880/368896</a>) stresses the point that prvalues are "like" the old-style rvalues, whereas the new xvalues allow for "lvalue-like" behavior.</p> <p>However, consider the following code:</p> <pre><code>class X {}; X foo() { return X(); } int main() { foo() = X(); // foo() is a prvalue that successfully appears on the lhs } </code></pre> <p>In this example, the expression <code>foo()</code> is a prvalue that appears on the left-hand side, and accepts assignment.</p> <p>That got me thinking - the logic that "xvalues" differ from "prvalues" because xvalues (glvalues that they are) can appear on the left-hand-side, seems to be broken by this example. Here we have a prvalue - which is not a glvalue - appearing successfully on the lhs and accepting assignment.</p> <p>(Note: in the case of POD, the above example would not compile, so for POD, the distinction between xvalues and prvalues seems to make sense. Therefore, this question is specifically in regards to non-POD types.)</p> <p>What, then, is the true difference in either allowed usage, or behavior, between an xvalue and a prvalue, that necessitates this distinction being written into the standard? A single example of a difference would be a fine alternative answer.</p> <p><strong>ADDENDUM</strong></p> <p>Pubby's comment was correct. The lifetime of a prvalue is extended by the compiler, but the lifetime of an xvalue is not.</p> <p>So, here is an answer to the question:</p> <p>Consider the following code:</p> <pre><code>// *** // Answer to question, from Pubby's comment // *** class X { public: X() : x(5) {} int x; }; X foo() { return X(); } X&amp;&amp; goo() { return std::move(X()); } // terrible coding, but makes the point int main() { foo() = X(); X&amp;&amp; x1 = foo(); // prvalue - lifetime extended! Object resides directly on stack as return value X&amp;&amp; x2 = goo(); // xvalue - lifetime not extended. Object (possibly polymorphic) resides somewhere else. x1.x = 6; x2.x = 7; // Danger! std::cout &lt;&lt; x1.x &lt;&lt; std::endl; // Just fine std::cout &lt;&lt; x2.x &lt;&lt; std::endl; // prints garbage in VS 2012 } </code></pre> <p>This demonstrates a difference in behavior between a prvalue, and an xvalue. Here we have identical client code except for the difference in binding (prvalue vs. xvalue).</p> <p>As the sample code demonstrates, the lifetime of the prvalue is automatically extended, but the lifetime of the xvalue is not.</p> <p>There are other obvious differences revealed, as well: For the prvalue, the object itself appears on the stack as the return value of the function; correspondingly, because a prvalue's static type is guaranteed to be its dynamic type (see answer below), extending its lifetime is meaningful and can be done by the compiler.</p> <p>On the other hand, for the xvalue, the object is at some unknown, arbitrary location, so the compiler couldn't easily extend its lifetime, especially given that the type could be polymorphic.</p> <p>Thanks for the answer.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

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