<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Anfänger std::move]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe immer wieder mal ein Problem mit move aus C++0x.</p>
<pre><code class="language-cpp">class A {
static A&amp;&amp; createA () { A a; std::move(a); };
}

//----------
A a = A::createA ();
</code></pre>
<p>Ist das soweit korrekt?<br />
Wann benötige ich einen Move-Constructor in der Klasse?<br />
Wann setzt man std::forward ein?</p>
<p>Danke, Thomas</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/292337/anfänger-std-move</link><generator>RSS for Node</generator><lastBuildDate>Sat, 25 Jul 2026 22:46:19 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/292337.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 07 Sep 2011 15:55:06 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 15:55:06 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe immer wieder mal ein Problem mit move aus C++0x.</p>
<pre><code class="language-cpp">class A {
static A&amp;&amp; createA () { A a; std::move(a); };
}

//----------
A a = A::createA ();
</code></pre>
<p>Ist das soweit korrekt?<br />
Wann benötige ich einen Move-Constructor in der Klasse?<br />
Wann setzt man std::forward ein?</p>
<p>Danke, Thomas</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116275</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116275</guid><dc:creator><![CDATA[Siassei]]></dc:creator><pubDate>Wed, 07 Sep 2011 15:55:06 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 16:15:19 GMT]]></title><description><![CDATA[<p>Nein, was du machen willst geht einfach ganz normal wie früher, etwa so:</p>
<pre><code class="language-cpp">class A 
{
    static A createA () 
    { 
        A a; 
        //der compiler wird a direkt dorthin konstruieren, wo es nach dem function
        //call hingehört, also...
        return a; 
    };
}

//----------
A a = A::createA () /* ...hierher */ ;
</code></pre>
<p>Ich empfehle dir<br />
<a href="http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/" rel="nofollow">http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/</a><br />
und<br />
<a href="http://thbecker.net/articles/rvalue_references/section_01.html" rel="nofollow">http://thbecker.net/articles/rvalue_references/section_01.html</a><br />
durchzulesen, mir hats geholfen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116280</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116280</guid><dc:creator><![CDATA[GorbGorb]]></dc:creator><pubDate>Wed, 07 Sep 2011 16:15:19 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 16:37:24 GMT]]></title><description><![CDATA[<p>Siassei schrieb:</p>
<blockquote>
<p>Ist das soweit korrekt?</p>
</blockquote>
<p>Nein, da du hier eine Referenz auf eine lokale Variable zurückgibst. RValue Referenzen sind auch nur Referenzen.</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>Wann benötige ich einen Move-Constructor in der Klasse?</p>
</blockquote>
<p>Immer dann, wenn du deinen Typen moveable machen möchtest. Ein Beispiel wäre ein Socket, ein Thread oder ein Mutex, also typische Resourcen. Auch Files könnte man moveable machen.</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>Wann setzt man std::forward ein?</p>
</blockquote>
<p>Immer dann, wenn du &quot;perfect forwarding&quot; haben möchtest. Aber ich denke das geht nun zu weit, auch wird man forward eher selten brauchen.</p>
<p>Da du Anfänger bist, würde ich dir empfehlen, von RValue Referenzen sowie std::move und std::forward erst mal die Finger zu lassen. Das ganze Zeug ist nicht einfach, wenn dann noch Templates hinzukommen wirds richtig lustig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116288</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116288</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Wed, 07 Sep 2011 16:37:24 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 21:47:47 GMT]]></title><description><![CDATA[<p>Siassei schrieb:</p>
<blockquote>
<p>ich habe immer wieder mal ein Problem mit move aus C++0x.</p>
<pre><code class="language-cpp">class A {
static A&amp;&amp; createA () { A a; std::move(a); };
}

//----------
A a = A::createA ();
</code></pre>
<p>Ist das soweit korrekt?</p>
</blockquote>
<p>Ganz und gar nicht.<br />
- Das return fehlt (U.B.)<br />
- Selbst mit return würdest du eine Referenz auf ein lokales Objekt zurückgeben (U.B.)<br />
- Selbst ohne Referenz ist das std::move dort eher schädlich (Du verhinderst damit Optimierungen, die viel besser sind als move-konstruktionen)</p>
<p>Korrekt:</p>
<pre><code class="language-cpp">class A {
public:
static A createA() { A a; return a; };
};

//----------
A a = A::createA ();
</code></pre>
<p>Wenn Du jetzt verhindern willst, dass das A-Objekt hier ggf <em>kopiert</em> wird, brauchst Du für A einen Move-Konstruktor.</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>Wann benötige ich einen Move-Constructor in der Klasse?</p>
</blockquote>
<p>s.o.</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>Wann setzt man std::forward ein?</p>
</blockquote>
<p>Typischerweise dann, wenn man &quot;Perfect Forwarding&quot; haben will. Manchmal aber auch so.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116317</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116317</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 07 Sep 2011 21:47:47 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 20:33:32 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<pre><code class="language-cpp">class A {
static A createA() { A a; return a; };
};

//----------
A a = A::createA ();
</code></pre>
<p>Wenn Du jetzt verhindern willst, dass das A-Objekt hier ggf <em>kopiert</em> wird, brauchst Du für A einen Move-Konstruktor.</p>
</blockquote>
<p>Nur einen move-Constructor? Oder muss die Function nicht<br />
static A&amp;&amp; createA() { A a; return a; };<br />
heisen?</p>
<p>Das Beispiel ist sehr einfach gehalten und ja, ich möchte das Kopieren verhindern.</p>
<p>z.B.<br />
- ein Interface ist als Header-Only deklariert<br />
- in einer DLL wird das Interface deklariert<br />
- in einer weiteren DL (DynamicLibrary) wird nun die Instance für das Interface angefordert.<br />
Ich kann mir nicht vorstellen, dass der Compiler über DL-Grenzen hinweg optimiert. Zudem möchte ich nun endlich verstehen, für was alles man das ganze Einsetzen kann und bin eben auf diesen Anwendungsfall gestossen.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/22268">@Pi</a><br />
Alles was C++0x betrifft bin ich absoluter Anfänger. Beim Rest würde ich mich nicht als solches Bezeichnen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Gruß, Thomas</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116383</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116383</guid><dc:creator><![CDATA[Siassei]]></dc:creator><pubDate>Wed, 07 Sep 2011 20:33:32 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 21:04:04 GMT]]></title><description><![CDATA[<p>Siassei schrieb:</p>
<blockquote>
<p>Oder muss die Function nicht<br />
static A&amp;&amp; createA() { A a; return a; };<br />
heisen?</p>
</blockquote>
<p>Nein. Man gibt keine Referenzen auf funktionslokale Objekte zurück. Das war früher schon so und so ist es immer noch. (Ich wiederhole mich)</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>Das Beispiel ist sehr einfach gehalten und ja, ich möchte das Kopieren verhindern.</p>
</blockquote>
<p>Dann spendiere Deiner Klasse einen move-ctor. (Ich wiederhole mich)</p>
<p>Siassei schrieb:</p>
<blockquote>
<p>[...Interface-Gedöns...Compiler-Optimierung...]</p>
</blockquote>
<p>WTF?!<br />
Lies bitte die verlinkten Artikel.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116391</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116391</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 07 Sep 2011 21:04:04 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 20:57:33 GMT]]></title><description><![CDATA[<blockquote>
<p>Nur einen move-Constructor? Oder muss die Function nicht<br />
<code>static A&amp;&amp; createA() { A a; return a; };</code><br />
heisen?</p>
</blockquote>
<p>Nur den Movekonstruktor und als Rückgabewert einfach nur &quot;A&quot;.</p>
<p>Ich hoffe ich irre mich nicht, aber std::move braucht man eigentlich nur, um Variablen <em>frühzeitig</em> zu moven.<br />
Im Fall <code>A createA() {A a; return a;}</code> weiß der Compiler ja, dass das Objekt <code>a</code> nach der return-Anweisung in der Funktion nicht mehr gebraucht wird - deshalb kann er es in das &quot;Rückgabeobjekt&quot; rein-moven.</p>
<p>Ein sinnvoller Anwendungsfall für std::move wäre aber z.B.:</p>
<pre><code class="language-cpp">void doSomething( foo Foo );

int main() {
    foo Objekt;
    doSomething( std::move(Objekt) );
    std::cout &lt;&lt; &quot;Whatever\n&quot;;
}
</code></pre>
<p>Hier kann der Compiler nicht automatisch das Objekt für den Parameter moven, weil er nicht weiß, ob es evtl in den Innereien von std::cout noch gebraucht wird; deshalb würde er es kopieren. Mit unserer Angabe von std::move sagen wir, dass wir das Objekt danach eben nicht mehr brauchen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116392</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116392</guid><dc:creator><![CDATA[fdfdg]]></dc:creator><pubDate>Wed, 07 Sep 2011 20:57:33 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Wed, 07 Sep 2011 22:31:57 GMT]]></title><description><![CDATA[<p>Siassei schrieb:</p>
<blockquote>
<p>krümelkacker schrieb:</p>
<blockquote>
<pre><code class="language-cpp">class A {
static A createA() { A a; return a; };
};

//----------
A a = A::createA ();
</code></pre>
<p>Wenn Du jetzt verhindern willst, dass das A-Objekt hier ggf <em>kopiert</em> wird, brauchst Du für A einen Move-Konstruktor.</p>
</blockquote>
<p>Nur einen move-Constructor? Oder muss die Function nicht<br />
static A&amp;&amp; createA() { A a; return a; };<br />
heisen?</p>
<p>Das Beispiel ist sehr einfach gehalten und ja, ich möchte das Kopieren verhindern.</p>
<p>z.B.<br />
- ein Interface ist als Header-Only deklariert<br />
- in einer DLL wird das Interface deklariert<br />
- in einer weiteren DL (DynamicLibrary) wird nun die Instance für das Interface angefordert.<br />
Ich kann mir nicht vorstellen, dass der Compiler über DL-Grenzen hinweg optimiert. Zudem möchte ich nun endlich verstehen, für was alles man das ganze Einsetzen kann und bin eben auf diesen Anwendungsfall gestossen.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/22268">@Pi</a><br />
Alles was C++0x betrifft bin ich absoluter Anfänger. Beim Rest würde ich mich nicht als solches Bezeichnen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Gruß, Thomas</p>
</blockquote>
<p>Das '&amp;&amp;' ist nichts Anderes als ein Zeiger, aber einer, der sagt, dass das Objekt, auf das er zeigt, nicht mehr benötigt wird (es wird danach nur noch der Destruktor aufgerufen). Wenn du also eine rvalue reference auf ein Objekt auf dem Funktionsstack zurückgibst, zeigt der Pointer irgendwo in undefinierten Bereich, weil das Objekt schon zerstört wurde. Im Grunde verhält sich das wie bei normalen Referenzen auch.<br />
Zum thema dlls und Optimierungen kann ich nichts genaues sagen, denke aber, dass es trotzdem funktioniert. Man kann ja der Funktion implizit einen Zeiger auf Speicher übergeben, auf den das Objekt dann konstruiert wird. Ich sehe nicht, warum das an dll Grenzen scheitern sollte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116418</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116418</guid><dc:creator><![CDATA[GorbGorb]]></dc:creator><pubDate>Wed, 07 Sep 2011 22:31:57 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 09:13:47 GMT]]></title><description><![CDATA[<p>Ich habe bisher zwei Dinge beobachtet. Leute, die sich ganz frisch mit dem Rvalue-Referenz-Thema (und dem ganzen Drumherum) auseinandersetzen gehen davon aus, dass...</p>
<ul>
<li>der <em>Compiler</em> irgendwie dafür zuständig ist, zu kontrollieren, <em>wie</em> Objekte von einem Ort zum anderen &quot;bewegt&quot; werden</li>
<li>sie als <em>Programmierer</em> selbst kontrollieren müssen, <em>wann</em> ein Objekt von einem Ort zum anderen &quot;bewegt&quot; (statt kopiert) wird.</li>
</ul>
<p>Es ist aber genau andersherum. Beispiel std::string. Es ist die Aufgabe desjenigen, der die Klasse schreibt, zu sagen, <em>wie genau</em> ein Objekt des Typs &quot;bewegt&quot; wird. Das passiert über die Move-Operationen (Move-Constructor, Move-Assignment-Operator). <em>Wann</em> ein Objekt bewegt statt kopiert werden kann, das weiß der Compiler selbst. Dafür gibt es Regeln. Diese Regeln sind <em>einfach</em> und <em>sehr praktisch</em>. Einfach deswegen, weil sie nicht fordern, dass ein Compiler komplizierte Analysen fahren muss, um zu sehen, wann wo was verwendet wird oder nicht. Praktisch deswegen, weil sie fast immer das richtige tun und im schlimmsten Fall eine unnötige Kopie erzeugen, die man dann aber per z.B. std::move() manuell umgehen kann.</p>
<pre><code class="language-cpp">class string {
  …
public:
  string(string const&amp;);            // copy ctor
  string(string &amp;&amp;);                // move ctor
  string&amp; operator=(string const&amp;); // copy assign
  string&amp; operator=(string &amp;&amp;)    ; // move assign
  ~sring();                         // dtor
  …
};
</code></pre>
<p>Bei den Move-Operationen darf das Quell-Objekt verändert werden, weil eine frisch initialisierte Rvalue-Referenz nur auf ein Objekt verweisen kann, welches keinen mehr interessiert. Entweder, weil es ein temporäres Objekt war und diese Referenz der einzige Weg ist, das Objekt noch zu erreichen, oder, weil der Nutzer explicit std::move() oder std::forward&lt;string&gt;() verwendet hat und uns damit sagt &quot;Das Ding interessiert mich nicht mehr&quot;. <em>So</em> kontrolliert der <em>Klassenautor</em>, <em>was</em> genau passieren soll. Typischerweise werden da nur ein paar Zeiger umgebogen und dabei das Quellobjekt &quot;geleert&quot;. Es ist also eigentlich nur interessant für Objekte, die einen Teil des Zustands irgendwo anders speichern und sich Zeiger dahin merken. Für normale POD-structs ist das mit den move-Operationen <em>völlig</em> uninteressant.</p>
<p>Bei Funktionen wie dieser:</p>
<pre><code class="language-cpp">string flip(string x)
{
  std::reverse(x.begin(),x.end());
  return x;
}

int main()
{
  string z = flip(flip(&quot;hello!&quot;));

  //           &quot;z&quot;  ist ein Lvalue-Ausdruck
  // &quot;std::move(z)&quot; ist ein Rvalue-Ausdruck,
  //                der sich auf _dasselbe_ Objekt bezieht

  // string w = z;         // Lvalue --&gt; Copy-ctor
  string w = std::move(z); // Rvalue --&gt; Move-Ctor
}
</code></pre>
<p>muss der Nutzer <em>nichts</em> besonderes machen, um von der move-optimierten Klasse profitieren zu können. x bezieht sich auf ein Funktions-lokales Objekt. Die Regeln sagen, dass bei so etwas wie &quot;return x;&quot;, wobei x sich auf ein solches Funktions-lokales Objekt bezieht, <em>nur dann</em> kopiert wird, wenn (a) der Compiler diesen Vorgang nicht wegoptimieren (copy elision) kann <em>und</em> (b) die Klasse keinen Move-Ctor hat. string hat hier aber einen Move-Ctor. Es wird also niemals im ganzen obigen Beispielprogramm unnötig kopiert.</p>
<p>Was macht std::move jetzt eigentlich? Die Antwort darauf ist: Nichts. Nichts, was irgendwie Zeit kosten würde. Es ist nur dazu da, um aus einem Lvalue ein Rvalue zu machen. Da wird nichts kopiert und nichts bewegt. Das, was std::move zurückgibt ist eine Referenz auf dasselbe Objekt, was man reingesteckt hat. Nur ist der std::move()-Ausdruck jetzt einer, der dazu führen kann, dass bei der Overload resolution eben ein move-ctor statt eines copy-ctors verwendet wird, respektive ein move-assign statt copy-assign -- sofern vorhanden. std::move() ist nur ein &quot;Move Request&quot;. Wenn die Klasse diese Funktionen nicht anbietet, dann wird eben ganz normali <em>kopiert</em>.</p>
<p>Was sind jetzt Lvalues und Rvalues? Das ist leider mit das Komplizierteste, wenn man all die Details verstehen will. Es gibt keine schöne kurze Definition davon. Es gibt Faustregeln, Gedächtnisstützen, die aber nicht 100% korrekt sind. 100% korrekt sind Listen von Beispielen, die genau aufzählen, welche Ausdrücke welche &quot;Wert-Kategorie&quot; haben. Ich versuche es mal ganz allgemein: Ein Rvalue ist ein Ausdruck, der einen Wert liefert oder sich auf ein Objekt beziehet, für den/das sich sonst keiner mehr außer dem direkten Empfänger interessiert. Alles andere sind Lvalues. Ich komme aber wahrscheinlich nicht drum herum, Beispiele zu nennen:</p>
<ul>
<li>Nicht-String-Literale sind <strong>R</strong>values (Beispiel: 3.1415)</li>
<li>(4+5.0)*3 ist ein <strong>R</strong>value</li>
<li>i++ ist ein <strong>R</strong>value (angenommen i ist ein int)</li>
<li>Funktionsaufrufe, die keine Lvalue-Referenz zurückgeben -- einschließlich expliziter Konstruktor-Aufruf für temporäre Objekte a la string(&quot;foo&quot;) -- sind <strong>R</strong>values</li>
<li>Das Ergebnis einer implizierten Konvertierung ist ein <strong>R</strong>value sofern der Ergebnis-Typ keine Lvalue-Referenz ist</li>
<li>Namen, die sich direkt auf Objekte beziehen, sind <strong>L</strong>values</li>
<li>String-Literale sind <strong>L</strong>values (beziehen sich auf langlebiges Array)</li>
<li>++i ist ein <strong>L</strong>value (angenommen i ist ein int)</li>
<li>Ein Zeiger-Dereferenzierungs-Ausdruck ist ein <strong>L</strong>value (Beispiel: *ptr oder ptr[22])</li>
<li>Funktionsaufrufe von Funktionen, die Lvalue-Referenzen zurückgeben, sind <strong>L</strong>values (Beispiele: meinvektor[22], *mysharedptr)</li>
</ul>
<p>Ich habe hier viele Fälle ausgelassen. Das müsste aber für's erste reichen. Und soooo wichtig ist das eigentlich auch nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116477</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116477</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Thu, 08 Sep 2011 09:13:47 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 08:17:43 GMT]]></title><description><![CDATA[<p><a href="http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx" rel="nofollow">Hier</a> gibt es einen brauchbaren Artikel zu dem Thema. Der beschreibt auch, was lvalues und rvalues überhaupt sind. Außerdem geht er auch auf die typischen Anfängerfehler bei den rvalue-Referenzen ein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116496</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116496</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 08 Sep 2011 08:17:43 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 09:31:52 GMT]]></title><description><![CDATA[<p>Ganz simpel zusammengefasst, machen Move-Konstruktoren und move-Assignment nur dann Sinn, wenn du in der Klasse eine oder mehrere Ressourcen nach RAII-Art hälst.<br />
Bisher hieß Rvalue-Kopieren von solchen Klassen immer folgendes:</p>
<p>Kopierendes Objekt legt neue Ressource an, die die Ressource des Originals kopiert.<br />
Originalobjekt wird zerstört, mit ihm die Originalressource.</p>
<p>Move-Operationen machen es wie folgt:<br />
Kopierendes Objekt übernimmt die Ressource des Originals. Keine tiefen Kopien nötig, kein Anlegen der neuen Ressource nötig.<br />
Originalobjekt wird (ohne Originalressource) zerstört.</p>
<p>Stell dir eine sehr vereinfachte Version des std::vector vor. Er enhält einen Pointer auf die Daten (dynamisches Array) und ein size_t, das weiß, wieviele Daten es sind, d.h. wie groß das Array ist. Der Copy-Ctor kopiert den size_t, legt ein neues dynamisches Array an und kopiert den Inhalt des Original-Arrays ins neue Array. Das Original stirbt, zerstört alle Element und gibt das Array frei.<br />
Der Move-Ctor kopiert den size_t (bei einfache Datentypen gibts nichts zu moven!), kopiert danach den Pointer und setzt den Pointer im Original auf 0. Nimmt also quasi dem Original seine Ressource (das dynamische Array) einfach weg. Das Original stirbt und nimmt nur seinen size_t mit ins Grab.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116525</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116525</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Thu, 08 Sep 2011 09:31:52 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 09:27:44 GMT]]></title><description><![CDATA[<p>Tachyon, der von Dir verlinkte Artikel ist leider nicht mehr aktuell. Es gab seitdem zwei wichtige Änderungen bei den Rvalue-Referenz-Regeln. Heute verweist eine frisch initialisierte non-const Rvalue-Referenz immer nur auf ein Objekt, was verändert werden darf, ohne dass es jemanden stören würde. Anfang 2009 konnte man aber noch schreiben</p>
<pre><code class="language-cpp">int    i  = 0;
int &amp;&amp; rr = i;
</code></pre>
<p>Das kompiliert jetzt aber nicht mehr. Man hat aus Sicherheitsgründen die Regeln abgeändert, weil es sonst zu versehentlichen Modifikationen von anderen Objekten hätte kommen können.</p>
<p>Wer gesprochenes amerikanisches Englisch versteht, kann sich ja mal Stephan T. Lavavej's <a href="http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Stephan-T-Lavavej-Standard-Template-Library-STL-9-of-n" rel="nofollow">Vortrag</a> anhören.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116527</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116527</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Thu, 08 Sep 2011 09:27:44 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 12:04:25 GMT]]></title><description><![CDATA[<p>Hallo,<br />
ich habe mal in einer Klasse den Move-Copy-Ctor und den Move Assignment Operator implementiert. Falls etwas besser gemacht werden könnte, bitte sagen.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;string&gt;

class X
{
private:
	std::vector&lt;std::string&gt; * m_pResource;
public:
	X():m_pResource(new std::vector&lt;std::string&gt;) {}
	~X() { delete m_pResource; 
			m_pResource = nullptr;}

	X(X const&amp; other); //normal copy ctor
	X(X&amp;&amp; tmp); //move copy ctor
	X&amp; operator= (X const&amp; rhs); //normal assignment operator
	X&amp; operator=(X&amp;&amp; tmp); //Move assignment operator

};

X::X(X const&amp; other)
{
	std::cout &lt;&lt; &quot;Copy Ctor\n&quot;;
	m_pResource = new std::vector&lt;std::string&gt;(*other.m_pResource); //teuer
}

X::X(X&amp;&amp; tmp)
{
	std::cout &lt;&lt; &quot;Move Copy Ctor\n&quot;;
	m_pResource = nullptr;
	std::swap(m_pResource,tmp.m_pResource);
}

X&amp; X::operator=(X&amp;&amp; tmp)
{
	std::cout &lt;&lt; &quot;Move Assignmnet Operator\n&quot;;
	std::swap(m_pResource,tmp.m_pResource);
	return *this;
}

X&amp; X::operator= (X const&amp; rhs)
{	
	if (this != &amp;rhs)
	{
		std::cout &lt;&lt; &quot;Assignment operator\n&quot;;
		std::vector&lt;std::string&gt; * tmp = new std::vector&lt;std::string&gt;(*rhs.m_pResource); //teuer
		std::swap(m_pResource,tmp);
	}
	return *this;
}

X foo() 
{
	X x;
	return x;
}

int main()
{
	X x;
	std::cout &lt;&lt; &quot;x = foo(); \n&quot;;
	x = foo(); //Ohne Move Ctor und ohne Move Assignment operator wird zuerst der Copy-Ctor aufgerufen und anschließend der Assignment operator aufgerufen (ohne NRVO)
			   //in beiden Fällen wird die Resource teuer kopiert 
				//mit NRVO: nur der Assignment operator wird aufgerufen

			  //mit Move Copy-Ctor und Move Assignmnet operator wird zuerst der MoveCopy-Ctor und anschließend der Move Assignment operator aufgerufen (ohne NRVO)
			  //in beiden Fällen werden nur Pointer umgebogen
			  //mit NRVO: nur der Move Assignment operator wird aufgerufen

	std::cout &lt;&lt; &quot;X y = x \n&quot;;
	X y =x; //x ist kein rvlaue -&gt; copy ctor
	std::cout &lt;&lt; &quot;X v; v = x;\n&quot;;
	X v;
	v = x; //x ist kein rvlaue  -&gt; assignment operator
	std::cout &lt;&lt; &quot;X z;z = X();\n&quot;;
	X z;
	z = X(); // X() ist ein Rvalue -&gt; move assignment operator
	std::cout &lt;&lt; &quot;X t = std::move(z);\n&quot;;
	X t = std::move(z);// z wird zum Rvalue -&gt; move copy ctor (auf z sollte nicht mehr zugegriffen werden)
	std::cout &lt;&lt; &quot;X c;c = std::move(t);\n&quot;;
	X c;
	c = std::move(t); //t wird zum Rvalue -&gt; move assignment operator (auf t sollte nicht mehr zugegriffen werden)

	return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2116630</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116630</guid><dc:creator><![CDATA[einwurf]]></dc:creator><pubDate>Thu, 08 Sep 2011 12:04:25 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 12:37:27 GMT]]></title><description><![CDATA[<p>einwurf schrieb:</p>
<blockquote>
<p>Falls etwas besser gemacht werden könnte, bitte sagen.</p>
</blockquote>
<p>Der kopierende Zuweisungsoperator führt etwas aus, was du bereits implementiert hast (und auch noch falsch, weil du den Speicher nicht freigibst). Zweckmäßigerweise sollte er eher so aussehen (Copy+Move, statt wie bisher Copy+Swap):</p>
<pre><code class="language-cpp">X&amp; X::operator= (X const&amp; rhs)
{   
    std::cout &lt;&lt; &quot;Assignment operator\n&quot;;
    return *this = X(rhs);
}
</code></pre>
<p>Außerdem prüfst du beim Kopieren nicht, ob evtl. das Argument bereits leer ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116644</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116644</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 08 Sep 2011 12:37:27 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 12:55:09 GMT]]></title><description><![CDATA[<p>[quote=&quot;camper&quot;]</p>
<p>einwurf schrieb:</p>
<blockquote>
<pre><code class="language-cpp">X&amp; X::operator= (X const&amp; rhs)
{   
    return *this = X(rhs);
}
</code></pre>
</blockquote>
<p>Was wird denn hier zurückgegeben? Also was ist der Rückgabewert einer zuweisung?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116653</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116653</guid><dc:creator><![CDATA[Fraaaggger]]></dc:creator><pubDate>Thu, 08 Sep 2011 12:55:09 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 13:13:22 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a>, stimmt. Eine Speicherlücke.<br />
Es geht aber noch einfacher (nur ein operator=), wenn ich nicht wieder etwas übersehen habe.</p>
<pre><code class="language-cpp">class X
{
private:
	std::vector&lt;std::string&gt; * m_pResource;
public:
	X():m_pResource(new std::vector&lt;std::string&gt;) {}
	~X() { delete m_pResource; 
			m_pResource = nullptr;}

	X(X const&amp; other); //normal copy ctor
	X(X&amp;&amp; tmp); //move copy ctor
	X&amp; operator= (X rhs); //Move assignment operator and normal assignment operator

};

X::X(X const&amp; other)
{
	std::cout &lt;&lt; &quot;Copy Ctor\n&quot;;
	m_pResource = new std::vector&lt;std::string&gt;(*other.m_pResource); //teuer
}

X::X(X&amp;&amp; tmp)
{
	std::cout &lt;&lt; &quot;Move Copy Ctor\n&quot;;
	m_pResource = nullptr;
	std::swap(m_pResource,tmp.m_pResource);
}

X&amp; X::operator= (X rhs)
{  
	std::cout &lt;&lt; &quot;Move and normal assignment operator\n&quot;;
    if(this != &amp;rhs) 
	{
		std::swap(m_pResource, rhs.m_pResource);
    }
	return *this;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2116663</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116663</guid><dc:creator><![CDATA[einwurf]]></dc:creator><pubDate>Thu, 08 Sep 2011 13:13:22 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 13:18:03 GMT]]></title><description><![CDATA[<p>Wenn ich auch mal einen Einwurf machen dürfte: Die Dinger heißen copy constructor, copy assignment operator, move constructor und move assignment operator. Insbesondere &quot;Move-Copy-Ctor&quot; ergibt keinen Sinn.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116666</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116666</guid><dc:creator><![CDATA[Bashar]]></dc:creator><pubDate>Thu, 08 Sep 2011 13:18:03 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 13:54:58 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/904">@Bashar</a>, danke. Ich dachte irrtümlich, weil der Copy-Ctor überladen wird heißt das nun ...</p>
<p>Das if(this != &amp;rhs) kann man sich auch sparen, da &quot;rhs&quot; ja immer ein anderes Objekt als &quot;this&quot; ist.<br />
Das swappen für den Fall x=x; sollte keine Probleme machen, oder?</p>
<pre><code class="language-cpp">X&amp; X::operator= (X rhs)
{  
    std::cout &lt;&lt; &quot;Move and normal assignment operator\n&quot;;
    std::swap(m_pResource, rhs.m_pResource);
    return *this;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2116670</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116670</guid><dc:creator><![CDATA[einwurf]]></dc:creator><pubDate>Thu, 08 Sep 2011 13:54:58 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 14:04:59 GMT]]></title><description><![CDATA[<p>einwurf schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a>, stimmt. Eine Speicherlücke.<br />
Es geht aber noch einfacher (nur ein operator=), wenn ich nicht wieder etwas übersehen habe.</p>
<pre><code class="language-cpp">...
</code></pre>
</blockquote>
<p>Das ist so möglich, aber im Movefall führst du so u.U. 2 Moves aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116674</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116674</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 08 Sep 2011 14:04:59 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 14:02:23 GMT]]></title><description><![CDATA[<p>Fraaaggger schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<pre><code class="language-cpp">X&amp; X::operator= (X const&amp; rhs)
{   
    return *this = X(rhs);
}
</code></pre>
</blockquote>
<p>Was wird denn hier zurückgegeben? Also was ist der Rückgabewert einer zuweisung?</p>
</blockquote>
<p>X(rhs) erzeugt ein temporäres Objekt, das dann für die Zuweisung genutzt wird. Weil es sich um ein rvalue handelt, wird die andere Zuweisungsüberladung aufgerufen, und somit das zurückgegeben, was die andere Funktion zurückgibt, also *this.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116677</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116677</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Thu, 08 Sep 2011 14:02:23 GMT</pubDate></item><item><title><![CDATA[Reply to Anfänger std::move on Thu, 08 Sep 2011 14:32:37 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Fraaaggger schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<pre><code class="language-cpp">X&amp; X::operator= (X const&amp; rhs)
{   
    return *this = X(rhs);
}
</code></pre>
</blockquote>
<p>Was wird denn hier zurückgegeben? Also was ist der Rückgabewert einer zuweisung?</p>
</blockquote>
<p>X(rhs) erzeugt ein temporäres Objekt, das dann für die Zuweisung genutzt wird. Weil es sich um ein rvalue handelt, wird die andere Zuweisungsüberladung aufgerufen, und somit das zurückgegeben, was die andere Funktion zurückgibt, also *this.</p>
</blockquote>
<p>Ahh! Jetzt machts sinn, danke! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2116707</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2116707</guid><dc:creator><![CDATA[ahaaaaa]]></dc:creator><pubDate>Thu, 08 Sep 2011 14:32:37 GMT</pubDate></item></channel></rss>