Note that there are some explanatory texts on larger screens.

plurals
  1. POHow is moving a const returned object possible?
    text
    copied!<p>Lately, I have been reading <a href="https://stackoverflow.com/questions/13099942/should-i-still-return-const-objects-in-c11">this post</a> and <a href="https://stackoverflow.com/questions/7138780/move-semantics-returning-const-values">that post</a> suggesting to stop returning const objects. This suggestion is also given by Stephan T. Lavavej in <a href="http://channel9.msdn.com/Events/GoingNative/2013/Don-t-Help-the-Compiler" rel="nofollow noreferrer">his talk</a> in Going Native 2013.</p> <p>I wrote a very simple test to help me understand which constructor/operator is called in all those cases:</p> <ul> <li>Returning const or non const objects</li> <li>What if Return Value Optimization (<a href="http://en.wikipedia.org/wiki/Return_value_optimization" rel="nofollow noreferrer">RVO</a>) kicks in ?</li> <li>What if Named Return Value Optimization (NRVO) kicks in ?</li> </ul> <p>Here is the test:</p> <pre><code>#include &lt;iostream&gt; void println(const std::string&amp;s){ try{std::cout&lt;&lt;s&lt;&lt;std::endl;} catch(...){}} class A{ public: int m; A():m(0){println(" Default Constructor");} A(const A&amp;a):m(a.m){println(" Copy Constructor");} A(A&amp;&amp;a):m(a.m){println(" Move Constructor");} const A&amp;operator=(const A&amp;a){m=a.m;println(" Copy Operator");return*this;} const A&amp;operator=(A&amp;&amp;a){m=a.m;println(" Move Operator");return*this;} ~A(){println(" Destructor");} }; A nrvo(){ A nrvo; nrvo.m=17; return nrvo;} const A cnrvo(){ A nrvo; nrvo.m=17; return nrvo;} A rvo(){ return A();} const A crvo(){ return A();} A sum(const A&amp;l,const A&amp;r){ if(l.m==0){return r;} if(r.m==0){return l;} A sum; sum.m=l.m+r.m; return sum;} const A csum(const A&amp;l,const A&amp;r){ if(l.m==0){return r;} if(r.m==0){return l;} A sum; sum.m=l.m+r.m; return sum;} int main(){ println("build a");A a;a.m=12; println("build b");A b;b.m=5; println("Constructor nrvo");A anrvo=nrvo(); println("Constructor cnrvo");A acnrvo=cnrvo(); println("Constructor rvo");A arvo=rvo(); println("Constructor crvo");A acrvo=crvo(); println("Constructor sum");A asum=sum(a,b); println("Constructor csum");A acsum=csum(a,b); println("Affectation nrvo");a=nrvo(); println("Affectation cnrvo");a=cnrvo(); println("Affectation rvo");a=rvo(); println("Affectation crvo");a=crvo(); println("Affectation sum");a=sum(a,b); println("Affectation csum");a=csum(a,b); println("Done"); return 0; } </code></pre> <p>And Here is the output in release mode (with NRVO and RVO): </p> <pre><code>build a Default Constructor build b Default Constructor Constructor nrvo Default Constructor Constructor cnrvo Default Constructor Constructor rvo Default Constructor Constructor crvo Default Constructor Constructor sum Default Constructor Move Constructor Destructor Constructor csum Default Constructor Move Constructor Destructor Affectation nrvo Default Constructor Move Operator Destructor Affectation cnrvo Default Constructor Copy Operator Destructor Affectation rvo Default Constructor Move Operator Destructor Affectation crvo Default Constructor Copy Operator Destructor Affectation sum Copy Constructor Move Operator Destructor Affectation csum Default Constructor Move Constructor Destructor Copy Operator Destructor Done Destructor Destructor Destructor Destructor Destructor Destructor Destructor Destructor </code></pre> <p>What I don't understant is this: <strong>why is the move constructor used in the "Constructor csum" test ?</strong></p> <p>The return object is const so I really feel like it should call the copy constructor.</p> <p><strong>What am I missing here ?</strong></p> <p>It should not be a bug from the compiler, both Visual Studio and clang give the same output.</p>
 

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