Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>As with many features of C++, there is a convention of how to use lvalue and rvalue references.</p> <p>Another example for conventions are the operators, especially <code>==</code> and <code>!=</code>. You could overload them to return <code>double</code>s, and copy files for the comparison. But per convention, they return <code>bool</code> and only compare the left and right operand without modifications.</p> <hr> <p>The convention for rvalue references is that they refer to objects whose resources can be "stolen":</p> <ul> <li>an lvalue reference implies that the object is owned by someone else</li> <li>an rvalue reference implies that the we can steal the resources from the object</li> </ul> <p>Rvalue references have been introduced to support move semantics, that is, transfer of ownership of resources. Move semantics conventionally implies that an object bound to an rvalue reference can be moved from. Moved-from objects conventionally are assumed to be in a <em>valid, but unknown state</em>. For example:</p> <pre><code>// returns a string that equals i appended to p string join(string&amp;&amp; p, int i); // string&amp;&amp; means: I do something to p. Or not. // append i to p void append(string&amp; p, int i); string my_string = "hello, world."; // length is 13 append(my_string, 42); // I know what state my_string is specified to be in now my_string[12] = "!"; // guaranteed to work string result = join( std::move(my_string), 42 ); // what state is my_string now in? char c = my_string[1]; // is this still guaranteed to work? string const cresult = join("hello, number ", 5); // fine, I don't care what state the temporary is in -- it's already destroyed </code></pre> <p>One could think of definitions like:</p> <pre><code>string join(string&amp;&amp; p, int i) { return std::move(p) + std::to_string(i); } void append(string&amp; p, int i) { p += std::to_string(i); } </code></pre> <p>This definition of <code>join</code> really <em>does</em> steal the resource from <code>p</code>, and the Standard really doesn't specify the state of <code>p</code> after the operation <code>std::move(p) + std::to_int(i)</code> (which creates a temporary that steals the resource from <code>p</code>).</p> <p>For this simple example, you could still use</p> <pre><code>string result = "hello "; result = join(std::move(result), 42); </code></pre> <p>to "replace" <code>append</code>. But moves can also be expensive (they always also copy something), and multiple lvalue reference parameters cannot easily be replaced by this technique.</p> <p><sub>N.B. in my opinion, you should indicate in the name of a function when it takes an lvalue reference and modifies the argument. I certainly don't expect a function named <code>print_string2</code> to modify the string I pass in.</sub></p> <hr> <p>IMHO, it's the convention that the moved-from object is in a valid, but unspecified state that should keep you from using rvalue references everywhere.</p> <p>Additionally, there can be a slight performance impact when using too many moves as opposed to in-place manipulation à la <code>join</code>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    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