<?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[RValue Refs, std::move, best practice]]></title><description><![CDATA[<p>Im Thread <a href="http://www.c-plusplus.net/forum/319529" rel="nofollow">http://www.c-plusplus.net/forum/319529</a> kam folgendes Statement:</p>
<p>Nathan schrieb:</p>
<blockquote>
<p>Deswegen ist es optimal wenn man jede Funktion mit einer const LValue Referenz und einer RValue Referenz überlädt. Der erste Fall ist gut für LValues, der zweite Fall gut für RValues, da dort direkt ins Ziel gemoved werden kann, was billiger als eine Kopie ist.<br />
Da diese Überladungen bei N Argumenten zu 2^N Funktionen führen kann, nimmt man quasi als Kompromiss pass-by-Value. Bei LValues wird ins Argument kopiert und dann kann man vom Argument ins Ziel moven (explizit mit std::move), bei RValues wird ins Argument gemoved und man kann dan wie bei LValues ins Ziel moven.</p>
</blockquote>
<p>Klingt vernuenftig.</p>
<p>Deswegen ein Verstaendisfragen zu &quot;best practice&quot; anhand etwas aelteren Code von mir <a href="http://ideone.com/CImxeL" rel="nofollow">http://ideone.com/CImxeL</a> bzgl. Nathans Anmerkungen. Es ist eine Messagequeue fuer multithreaded Producer/Consumer abgeleitet aus der Reihe <a href="http://www.youtube.com/playlist?list=PL1835A90FC78FF8BE" rel="nofollow">http://www.youtube.com/playlist?list=PL1835A90FC78FF8BE</a> . Explizit geht es um die Methode:</p>
<pre><code class="language-cpp">void post(T&amp;&amp; msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.push_front(std::move(msg));
    cond.notify_one();
}
</code></pre>
<p>Grundgedanke war, dass keine Messages kopiert werden sollen.</p>
<p><strong>Variante 1</strong>: Weicht man diese Anforderung auf, so waere es gut, zwei Methoden anzubieten:</p>
<pre><code class="language-cpp">void post(T const&amp; msg) ... // copy messages
void post(T&amp;&amp; msg) ... // move messages
</code></pre>
<p>Welche Methode wird bei temporaeren Objekten aufgerufen?</p>
<p><strong>Variante 2</strong>: Da es wie schon gesagt fuer mehr Parameter recht aufwendig wird, sollte nur eine Methode angeboten werden:</p>
<pre><code class="language-cpp">void post(T msg)
</code></pre>
<p>Und es wird dem Aufrufer ueberlassen, zu verschieben oder zu kopieren:</p>
<pre><code class="language-cpp">q.post(my_ms); // copy message
q.post(std::move(my_msg)); // move message
</code></pre>
<p>Prinzipiell gefaellt mir der Gedanke, den Benutzer entscheiden zu lassen, ob kpiert werden soll</p>
<p>Meine Fragen: Ist <strong>Variante 2</strong> &quot;best practice&quot;? Gibt es Nachteile? Gibt es weitere Vorteile?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/319531/rvalue-refs-std-move-best-practice</link><generator>RSS for Node</generator><lastBuildDate>Sat, 25 Jul 2026 05:14:21 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/319531.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 22 Aug 2013 09:53:25 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 09:53:25 GMT]]></title><description><![CDATA[<p>Im Thread <a href="http://www.c-plusplus.net/forum/319529" rel="nofollow">http://www.c-plusplus.net/forum/319529</a> kam folgendes Statement:</p>
<p>Nathan schrieb:</p>
<blockquote>
<p>Deswegen ist es optimal wenn man jede Funktion mit einer const LValue Referenz und einer RValue Referenz überlädt. Der erste Fall ist gut für LValues, der zweite Fall gut für RValues, da dort direkt ins Ziel gemoved werden kann, was billiger als eine Kopie ist.<br />
Da diese Überladungen bei N Argumenten zu 2^N Funktionen führen kann, nimmt man quasi als Kompromiss pass-by-Value. Bei LValues wird ins Argument kopiert und dann kann man vom Argument ins Ziel moven (explizit mit std::move), bei RValues wird ins Argument gemoved und man kann dan wie bei LValues ins Ziel moven.</p>
</blockquote>
<p>Klingt vernuenftig.</p>
<p>Deswegen ein Verstaendisfragen zu &quot;best practice&quot; anhand etwas aelteren Code von mir <a href="http://ideone.com/CImxeL" rel="nofollow">http://ideone.com/CImxeL</a> bzgl. Nathans Anmerkungen. Es ist eine Messagequeue fuer multithreaded Producer/Consumer abgeleitet aus der Reihe <a href="http://www.youtube.com/playlist?list=PL1835A90FC78FF8BE" rel="nofollow">http://www.youtube.com/playlist?list=PL1835A90FC78FF8BE</a> . Explizit geht es um die Methode:</p>
<pre><code class="language-cpp">void post(T&amp;&amp; msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.push_front(std::move(msg));
    cond.notify_one();
}
</code></pre>
<p>Grundgedanke war, dass keine Messages kopiert werden sollen.</p>
<p><strong>Variante 1</strong>: Weicht man diese Anforderung auf, so waere es gut, zwei Methoden anzubieten:</p>
<pre><code class="language-cpp">void post(T const&amp; msg) ... // copy messages
void post(T&amp;&amp; msg) ... // move messages
</code></pre>
<p>Welche Methode wird bei temporaeren Objekten aufgerufen?</p>
<p><strong>Variante 2</strong>: Da es wie schon gesagt fuer mehr Parameter recht aufwendig wird, sollte nur eine Methode angeboten werden:</p>
<pre><code class="language-cpp">void post(T msg)
</code></pre>
<p>Und es wird dem Aufrufer ueberlassen, zu verschieben oder zu kopieren:</p>
<pre><code class="language-cpp">q.post(my_ms); // copy message
q.post(std::move(my_msg)); // move message
</code></pre>
<p>Prinzipiell gefaellt mir der Gedanke, den Benutzer entscheiden zu lassen, ob kpiert werden soll</p>
<p>Meine Fragen: Ist <strong>Variante 2</strong> &quot;best practice&quot;? Gibt es Nachteile? Gibt es weitere Vorteile?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347744</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347744</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Thu, 22 Aug 2013 09:53:25 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:11:33 GMT]]></title><description><![CDATA[<p>Korrigiert mich wenn ich falsch liege, aber so wie ich das sehe, sind beide Varianten vom Aufrufverhalten gleich und auch das Verhalten ist praktisch identisch. Der Unterschied: Bei Variante 1 spart man sich einen zusätzlichen move, dafür muss man aber zwei Varianten implementieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347749</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347749</guid><dc:creator><![CDATA[TNA]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:11:33 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:34:30 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>in einem Thread von mir gab es eine ganze Reihe von Antworten, die viele Details dazu geben, was man in welchem Fall optimal einsetzen sollte. Vielleicht hilft Dir das <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="🙂"
    /><br />
<a href="http://www.c-plusplus.net/forum/314315" rel="nofollow">http://www.c-plusplus.net/forum/314315</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347756</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347756</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:34:30 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:36:25 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<p><strong>Variante 1</strong>: Weicht man diese Anforderung auf, so waere es gut, zwei Methoden anzubieten:</p>
<pre><code class="language-cpp">void post(T const&amp; msg) ... // copy messages
void post(T&amp;&amp; msg) ... // move messages
</code></pre>
<p>Welche Methode wird bei temporaeren Objekten aufgerufen?</p>
</blockquote>
<p>Bei Temporären Variablen wird natürlich die zweite Variante aufgerufen.</p>
<blockquote>
<p><strong>Variante 2</strong>: Da es wie schon gesagt fuer mehr Parameter recht aufwendig wird, sollte nur eine Methode angeboten werden:</p>
<pre><code class="language-cpp">void post(T msg)
</code></pre>
<p>Und es wird dem Aufrufer ueberlassen, zu verschieben oder zu kopieren:</p>
<pre><code class="language-cpp">q.post(my_ms); // copy message
q.post(std::move(my_msg)); // move message
</code></pre>
<p>Prinzipiell gefaellt mir der Gedanke, den Benutzer entscheiden zu lassen, ob kpiert werden soll</p>
<p>Meine Fragen: Ist <strong>Variante 2</strong> &quot;best practice&quot;? Gibt es Nachteile? Gibt es weitere Vorteile?</p>
</blockquote>
<p>imho ist Variante 2 best practice. Nachteil ist, dass die unter Umständen nicht ganz so effizient sein kann.<br />
Kosten Variante 1:<br />
LValue: 1 copy (Argument zum Ziel).<br />
RValue: 1 move (Argument zum Ziel).<br />
Kosten Variante 2:<br />
LValue: 1 copy (Quelle zum Argument), 1 move (Argument zum Ziel)<br />
RValue: 2 move (Temporary zum Argument, Argument zum Ziel)*</p>
<p>(Wenn man natürlich aus dem LValue ein RValue macht, ist das effizienter.)</p>
<p>*Ideone überrascht mich da aber: <a href="http://ideone.com/GtERzZ" rel="nofollow">http://ideone.com/GtERzZ</a><br />
Kann es sein, dass der Compiler das Temporary direkt im Argument erstellt?<br />
Wenn ja, ist diese Variante genauso gut, wie die mit T&amp;&amp;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347758</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347758</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:36:25 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:37:38 GMT]]></title><description><![CDATA[<p>Best Practise waere, beides anzubieten. Die Standardcontainer bieten auch beides an. Das heisst aber nicht, dass man nicht beides ueber die selbe Funktion implementieren kann:</p>
<pre><code>template &lt;typename T&gt;
void post_impl(T&amp;&amp; msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.push_front(std::forward&lt;T&gt;(msg));
    cond.notify_one();
}

void post(T const&amp; msg)
{
    post_impl(msg);
}

void post(T&amp;&amp; msg)
{
    post_impl(std::move(msg));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2347760</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347760</guid><dc:creator><![CDATA[Kellerautomat]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:37:38 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:42:52 GMT]]></title><description><![CDATA[<p>Kellerautomat schrieb:</p>
<blockquote>
<p>Best Practise waere, beides anzubieten. Die Standardcontainer bieten auch beides an.</p>
</blockquote>
<p>Klar, in diesem Fall wäre es das, da es nur ein Argument gibt.<br />
Hat man aber mehrere ist die Arbeit für den Programmierer doch etwas hoch.<br />
Ich hab mal eine Klasse gesehen, die das Argument entweder als LValue oder RValue Referenz speichert, jenachdem was es ist. Das ermöglicht dann effiziente Übergabe an die entsprechenden Copy/Movectors.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347761</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347761</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:42:52 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:47:00 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>*Ideone überrascht mich da aber: <a href="http://ideone.com/GtERzZ" rel="nofollow">http://ideone.com/GtERzZ</a><br />
Kann es sein, dass der Compiler das Temporary direkt im Argument erstellt?</p>
</blockquote>
<p>Wenn ich das richtig gelesen habe, ist es in der Tat so, dass Compiler nicht benötigte Kopien/Moves in Argumente komplett weg optimieren können, ähnlich wie beim Rückgabewert.</p>
<p>Nathan schrieb:</p>
<blockquote>
<p>Wenn ja, ist diese Variante genauso gut, wie die mit T&amp;&amp;.</p>
</blockquote>
<p>Fast, denn das weg optimieren geht wohl nur bei echten Temporaries und nicht bei std::move.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347764</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347764</guid><dc:creator><![CDATA[TNA]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:47:00 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 10:50:12 GMT]]></title><description><![CDATA[<p>Kellerautomats Code mit richtigen Bezeichnern:</p>
<pre><code>template &lt;typename... T&gt;
void emplace(T&amp;&amp;... msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.emplace_front(std::forward&lt;T&gt;(msg)...);
    cond.notify_one();
}

void post(T const&amp; msg)
{
    emplace(msg);
}

void post(T&amp;&amp; msg)
{
    emplace(std::move(msg));
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2347766</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347766</guid><dc:creator><![CDATA[emplac0r]]></dc:creator><pubDate>Thu, 22 Aug 2013 10:50:12 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 11:00:34 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Ich hab mal eine Klasse gesehen, die das Argument entweder als LValue oder RValue Referenz speichert, jenachdem was es ist. Das ermöglicht dann effiziente Übergabe an die entsprechenden Copy/Movectors.</p>
</blockquote>
<p>Hier sowas in der Art meinte ich: <a href="http://ideone.com/fTORB3" rel="nofollow">http://ideone.com/fTORB3</a><br />
Es kommen zwar zustätzliche Kosten (if Abfrage und ein weitere Def-Ctor), aber das ist in der Regel billig. Und man hat somit das beste von beiden Seiten: genau die Aufrufe, die man haben will, und wenig Tipparbeit.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347773</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347773</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 22 Aug 2013 11:00:34 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 11:05:36 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Hier sowas in der Art meinte ich: <a href="http://ideone.com/fTORB3" rel="nofollow">http://ideone.com/fTORB3</a><br />
Es kommen zwar zustätzliche Kosten (if Abfrage und ein weitere Def-Ctor), aber das ist in der Regel billig. Und man hat somit das beste von beiden Seiten: genau die Aufrufe, die man haben will, und wenig Tipparbeit.</p>
</blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347775</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347775</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 22 Aug 2013 11:05:36 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 11:23:08 GMT]]></title><description><![CDATA[<p>Hier noch eine verbesserte Version, die auch mit Konvertierungen klar kommt und keinen zustätzlichen Overhead (abgesehen vom if-else und dem Erzeugen das fast_arg) bietet: <a href="http://ideone.com/uIIPMi" rel="nofollow">http://ideone.com/uIIPMi</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347787</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347787</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Thu, 22 Aug 2013 11:23:08 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 12:09:26 GMT]]></title><description><![CDATA[<p>emplac0r schrieb:</p>
<blockquote>
<p>Kellerautomats Code mit richtigen Bezeichnern:</p>
<pre><code>template &lt;typename... T&gt;
void emplace(T&amp;&amp;... msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.emplace_front(std::forward&lt;T&gt;(msg)...);
    cond.notify_one();
}

void post(T const&amp; msg)
{
    emplace(msg);
}

void post(T&amp;&amp; msg)
{
    emplace(std::move(msg));
}
</code></pre>
</blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2347807</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347807</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Thu, 22 Aug 2013 12:09:26 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 12:39:57 GMT]]></title><description><![CDATA[<p>Warum nicht einfach so?</p>
<pre><code class="language-cpp">template &lt;typename U&gt;
void post(U &amp;&amp;msg)
{
    std::lock_guard&lt;std::mutex&gt; lock(mtx);
    queue.push_front(std::forward&lt;U&gt;(msg));
    cond.notify_one();
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2347822</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347822</guid><dc:creator><![CDATA[TyRoXx]]></dc:creator><pubDate>Thu, 22 Aug 2013 12:39:57 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Thu, 22 Aug 2013 12:49:33 GMT]]></title><description><![CDATA[<p>TyRoXx schrieb:</p>
<blockquote>
<p>Warum nicht einfach so?</p>
</blockquote>
<p>Um es sich nicht mit Stroustrup zu verscherzen.</p>
<p>Stroustrup schrieb:</p>
<blockquote>
<p>Improved push operations: My favorite container operation is push_back() that allows a container to grow gracefully:</p>
<pre><code class="language-cpp">vector&lt;pair&lt;string,int&gt;&gt; vp;
	string s;
	int i;
	while(cin&gt;&gt;s&gt;&gt;i) vp.push_back({s,i}); // {s,i} geht nur, wenn kein Template
</code></pre>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2347828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2347828</guid><dc:creator><![CDATA[emplac0r]]></dc:creator><pubDate>Thu, 22 Aug 2013 12:49:33 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Sat, 24 Aug 2013 08:52:39 GMT]]></title><description><![CDATA[<p>Danke fuer eure Vorschlaege, std::forward werde ich wohl etwas naeher beleuchten. Aber eine Hilfsklasse wird es nicht geben. Tipparbeit ist fuer mich nie ein Grund.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348245</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348245</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Sat, 24 Aug 2013 08:52:39 GMT</pubDate></item><item><title><![CDATA[Reply to RValue Refs, std::move, best practice on Sat, 24 Aug 2013 09:49:26 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<p>Danke fuer eure Vorschlaege, std::forward werde ich wohl etwas naeher beleuchten. Aber eine Hilfsklasse wird es nicht geben. Tipparbeit ist fuer mich nie ein Grund.</p>
</blockquote>
<p>Es geht nicht nur um Tipparbeit, sondern auch um Übersichtlichkeit und Wartbarkeit. Bei doppeltem Code kann man zwei Fehler korrigieren müssen oder in einer Implementierung einen Fehler haben, den man schwer findet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2348262</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2348262</guid><dc:creator><![CDATA[Marthog]]></dc:creator><pubDate>Sat, 24 Aug 2013 09:49:26 GMT</pubDate></item></channel></rss>