Note that there are some explanatory texts on larger screens.

plurals
  1. POCopy elision on Visual C++ 2010 Beta 2
    primarykey
    data
    text
    <p>I was reading <a href="http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/" rel="nofollow noreferrer"><em>Want Speed? Pass by Value</em></a> on the <a href="http://cpp-next.com" rel="nofollow noreferrer">C++ Next blog</a> and created <a href="http://pastebin.com/f39c826c6" rel="nofollow noreferrer">this program</a> to get a feel for copy elision and move semantics in C++0x:</p> <pre><code>#include &lt;vector&gt; #include &lt;iostream&gt; class MoveableClass { public: MoveableClass() : m_simpleData(0), instance(++Instances) { std::cout &lt;&lt; "Construct instance " &lt;&lt; instance &lt;&lt; " (no data)" &lt;&lt; std::endl; } MoveableClass(std::vector&lt;double&gt; data) : m_data(std::move(data)), m_simpleData(0), instance(++Instances) { std::cout &lt;&lt; "Construct instance " &lt;&lt; instance &lt;&lt; " (with data)" &lt;&lt; std::endl; } MoveableClass(int simpleData) : m_simpleData(simpleData), instance(++Instances) { std::cout &lt;&lt; "Construct instance " &lt;&lt; instance &lt;&lt; " (with simple data)" &lt;&lt; std::endl; } MoveableClass(const MoveableClass&amp; other) : m_data(other.m_data), m_simpleData(other.m_simpleData), instance(++Instances) { std::cout &lt;&lt; "Construct instance " &lt;&lt; instance &lt;&lt; " from a copy of " &lt;&lt; other.instance &lt;&lt; std::endl; Elided = false; } MoveableClass(MoveableClass&amp;&amp; other) : m_data(std::move(other.m_data)), m_simpleData(other.m_simpleData), instance(++Instances) { std::cout &lt;&lt; "Construct instance " &lt;&lt; instance &lt;&lt; " from a move of " &lt;&lt; other.instance &lt;&lt; std::endl; Elided = false; } MoveableClass&amp; operator=(MoveableClass other) { std::cout &lt;&lt; "Assign to instance " &lt;&lt; instance &lt;&lt; " from " &lt;&lt; other.instance &lt;&lt; std::endl; other.Swap(*this); return *this; } ~MoveableClass() { std::cout &lt;&lt; "Destroy instance " &lt;&lt; instance &lt;&lt; std::endl; --Instances; } void Swap(MoveableClass&amp; other) { std::swap(m_data, other.m_data); std::swap(m_simpleData, other.m_simpleData); } static int Instances; static bool Elided; private: int instance; int m_simpleData; std::vector&lt;double&gt; m_data; }; int MoveableClass::Instances = 0; bool MoveableClass::Elided = true; std::vector&lt;double&gt; BunchOfData() { return std::vector&lt;double&gt;(9999999); } int SimpleData() { return 9999999; } MoveableClass CreateRVO() { return MoveableClass(BunchOfData()); } MoveableClass CreateNRVO() { MoveableClass named(BunchOfData()); return named; } MoveableClass CreateRVO_Simple() { return MoveableClass(SimpleData()); } MoveableClass CreateNRVO_Simple() { MoveableClass named(SimpleData()); return named; } int main(int argc, char* argv[]) { std::cout &lt;&lt; "\nMove assign from RVO: " &lt;&lt; '\n'; { MoveableClass a; a = CreateRVO(); } std::cout &lt;&lt; "Move elided: " &lt;&lt; (MoveableClass::Elided ? "Yes" : "No") &lt;&lt; '\n'; MoveableClass::Elided = true; // reset for next test std::cout &lt;&lt; "\nMove assign from RVO simple: " &lt;&lt; '\n'; { MoveableClass a; a = CreateRVO_Simple(); } std::cout &lt;&lt; "Move elided: " &lt;&lt; (MoveableClass::Elided ? "Yes" : "No") &lt;&lt; '\n'; MoveableClass::Elided = true; // reset for next test std::cout &lt;&lt; "\nMove assign from NRVO: " &lt;&lt; '\n'; { MoveableClass a; a = CreateNRVO(); } std::cout &lt;&lt; "Move elided: " &lt;&lt; (MoveableClass::Elided ? "Yes" : "No") &lt;&lt; '\n'; MoveableClass::Elided = true; // reset for next test std::cout &lt;&lt; "\nMove assign from NRVO simple: " &lt;&lt; std::endl; { MoveableClass a; a = CreateNRVO_Simple(); } std::cout &lt;&lt; "Move elided: " &lt;&lt; (MoveableClass::Elided ? "Yes" : "No") &lt;&lt; '\n'; MoveableClass::Elided = true; // reset for next test } </code></pre> <p>Here is the output I get when compiled in release mode on Visual C++ 10.0 (Beta 2):</p> <blockquote> <p>Move assign from RVO:<br> Construct instance 1 (no data)<br> Construct instance 2 (with data)<br> Construct instance 3 from a move of 2<br> Destroy instance 2<br> Assign to instance 1 from 3<br> Destroy instance 3<br> Destroy instance 1<br> Move elided: No </p> <p>Move assign from RVO simple:<br> Construct instance 1 (no data)<br> Construct instance 2 (with simple data)<br> Assign to instance 1 from 2<br> Destroy instance 2<br> Destroy instance 1<br> Move elided: Yes </p> <p>Move assign from NRVO:<br> Construct instance 1 (no data)<br> Construct instance 2 (with data)<br> Assign to instance 1 from 2<br> Destroy instance 2<br> Destroy instance 1<br> Move elided: Yes </p> <p>Move assign from NRVO simple:<br> Construct instance 1 (no data)<br> Construct instance 2 (with simple data)<br> Assign to instance 1 from 2<br> Destroy instance 2<br> Destroy instance 1<br> Move elided: Yes</p> </blockquote> <p>However, I am perplexed by one thing. As you can see, all of the moves are elided except for the first one. Why can't the compiler perform RVO with a MoveableClass(std::vector) at line 86, but can with a MoveableClass(int) at line 97? Is this just a bug with MSVC or is there a good reason for this? And if there is a good reason, why can it still perform NRVO on a MoveableClass(std::vector) at line 91?</p> <p>I'd like to understand it so I can go to sleep happy. :)</p>
    singulars
    1. This table or related slice is empty.
    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.
 

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