Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <blockquote> <p>I am used to optimizations being constrained such that they cannot change observable behaviour.</p> </blockquote> </blockquote> <p>This is correct. As a general rule -- known as the <em>as-if</em> rule -- compilers can change code if the change is not observable.</p> <blockquote> <blockquote> <p>This restriction does not seem to apply to RVO. </p> </blockquote> </blockquote> <p>Yes. The clause quoted in the OP gives an exception to the <em>as-if</em> rule and allows copy construction to be omitted, even when it has side effects. Notice that the RVO is just one case of copy-elision (the first bullet point in C++11 12.8/31).</p> <blockquote> <blockquote> <p>Do I ever need to worry about the side effects mentioned in the standard?</p> </blockquote> </blockquote> <p>If the copy constructor has side effects such that copy elision when performed causes a problem, then you should reconsider the design. If this is not your code, you should probably consider a better alternative.</p> <blockquote> <blockquote> <p>What do I as a programmer need to do (or not do) to allow this optimization to be performed?</p> </blockquote> </blockquote> <p>Basically, if possible, return a local variable (or temporary) with the same cv unqualified type as the function return type. This allows RVO but doens't enforce it (the compiler might not perform RVO).</p> <blockquote> <blockquote> <p>For example, does the following prohibit the use of copy elision (due to the move):</p> </blockquote> </blockquote> <pre><code>// notice that I fixed the OP's example by adding &lt;double&gt; std::vector&lt;double&gt; foo(int bar){ std::vector&lt;double&gt; quux(bar, 0); return std::move(quux); } </code></pre> <p>Yes, it does because you're not returning the name of a local variable. This</p> <pre><code>std::vector&lt;double&gt; foo(int bar){ std::vector&lt;double&gt; quux(bar,0); return quux; } </code></pre> <p>allows RVO. One might be worried that if RVO is not performed then moving is better than coping (which would explain the use of <code>std::move</code> above). Don't worry about that. All major compilers will do the RVO here (at least in release build). Even if a compiler doesn't do RVO but the conditions for RVO are met then it will try to do a move rather than a copy. In summary, using <code>std::move</code> above will certainly make a move. Not using it will likely neither copy nor move anything and, in the worst (unlikely) case, will move.</p> <p>(<strong>Update:</strong> As haohaolee's pointed out (see comments), the following paragraphs are not correct. However, I leave them here because they suggest an idea that might work for classes that don't have a constructor taking a <code>std::initializer_list</code> (see the reference at the bottom). For <code>std::vector</code>, haohaolee found a workaround.)</p> <p>In this example you can force the RVO (strict speaking this is no longer RVO but let's keep calling this way for simplicity) by returning a <em>braced-init-list</em> from which the return type can be created:</p> <pre><code>std::vector&lt;double&gt; foo(int bar){ return {bar, 0}; // &lt;-- This doesn't work. Next line shows a workaround: // return {bar, 0.0, std::vector&lt;double&gt;::allocator_type{}}; } </code></pre> <p>See this <a href="https://stackoverflow.com/questions/19427196/construction-helper-function-make-xyz-where-xyx-is-a-class-with-noncopy-constrai">post</a> and <a href="https://stackoverflow.com/users/46642/r-martinho-fernandes">R. Martinho Fernandes</a>'s brilliant <a href="https://stackoverflow.com/a/19428052/1137388">answer</a>.</p> <p>Be carefull! Have the return type been <code>std::vector&lt;int&gt;</code> the last code above would have a different behavior from the original. (This is another story.)</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. 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.
 

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