<?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[Parameterübergabe R-Value und const-reference]]></title><description><![CDATA[<p>Hallo @all,</p>
<p>ich finde im Netz wiederkehrend widersprüchliche Aussagen welches der folgenden<br />
Lösungen mein Problem am besten löst.<br />
Zum Problem:<br />
Ich habe ein Thread, wobei seine Parameter beim Start kopiert bzw. verschoben werden müssen, da evtl. sonst die Lebenszeit des Threads, welcher diesen Thread startet, nicht lang genug ist. Um es dem Nutzer freizustellen, welche Version er nutzen möchte, benötige ich eine Version, die entscheidet, ob kopiert oder verschoben werden soll.</p>
<pre><code>/*
	Mein erster Ansatz unterscheidet bei den Funktionen zwischen
	const-reference und R-Value, wobei die const-reference eine Kopie
	erzeugt und dann die R-Value Version mit dieser Kopie aufruft.
	Problem:
	Bei n Parametern benötige ich 2^n Funktionen
*/
void foo( std::string&amp;&amp; )
{
	// Do Stuff
}

void foo( const std::string&amp; s )
{
	foo( std::move( std::string( s ) ) );
}

/*
	Hierbei sei es dem Nutzer überlassen, ob er mittels
	std::move den Parameter übergibt oder eine Kopie-erstellt.
	Problem:
	Möchte ich den String in der Funktion nochmals verschieben o.Ä., also muss ich nochmals std::move 
	aufrufen, ich habe also effektiv immer 1 move-Konstruktor Aufruf + 1 Move oder Copy Aufruf
*/
void foo( std::string s )
{
	//Do Stuff
}

/*
	Erscheint mit recht aufwendig und ich weiß nicht 100% ob ich das richtig
	verwendet habe
*/
template &lt; class T,
           class = typename std::enable_if&lt;std::is_is_convertible&lt;T,std::string&gt;::value&gt;::type&gt;
void foo( T&amp;&amp; )
{
	// Do Stuff
}
</code></pre>
<p>Soweit meine Ansätze. Evtl. gibt es auch noch eine andere? Welche von den ist sonst die zu empfehlene?</p>
<p>MfG</p>
<p>shft</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/333672/parameterübergabe-r-value-und-const-reference</link><generator>RSS for Node</generator><lastBuildDate>Sun, 26 Apr 2026 18:21:03 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/333672.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 23 Jul 2015 09:36:46 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Parameterübergabe R-Value und const-reference on Thu, 23 Jul 2015 09:36:46 GMT]]></title><description><![CDATA[<p>Hallo @all,</p>
<p>ich finde im Netz wiederkehrend widersprüchliche Aussagen welches der folgenden<br />
Lösungen mein Problem am besten löst.<br />
Zum Problem:<br />
Ich habe ein Thread, wobei seine Parameter beim Start kopiert bzw. verschoben werden müssen, da evtl. sonst die Lebenszeit des Threads, welcher diesen Thread startet, nicht lang genug ist. Um es dem Nutzer freizustellen, welche Version er nutzen möchte, benötige ich eine Version, die entscheidet, ob kopiert oder verschoben werden soll.</p>
<pre><code>/*
	Mein erster Ansatz unterscheidet bei den Funktionen zwischen
	const-reference und R-Value, wobei die const-reference eine Kopie
	erzeugt und dann die R-Value Version mit dieser Kopie aufruft.
	Problem:
	Bei n Parametern benötige ich 2^n Funktionen
*/
void foo( std::string&amp;&amp; )
{
	// Do Stuff
}

void foo( const std::string&amp; s )
{
	foo( std::move( std::string( s ) ) );
}

/*
	Hierbei sei es dem Nutzer überlassen, ob er mittels
	std::move den Parameter übergibt oder eine Kopie-erstellt.
	Problem:
	Möchte ich den String in der Funktion nochmals verschieben o.Ä., also muss ich nochmals std::move 
	aufrufen, ich habe also effektiv immer 1 move-Konstruktor Aufruf + 1 Move oder Copy Aufruf
*/
void foo( std::string s )
{
	//Do Stuff
}

/*
	Erscheint mit recht aufwendig und ich weiß nicht 100% ob ich das richtig
	verwendet habe
*/
template &lt; class T,
           class = typename std::enable_if&lt;std::is_is_convertible&lt;T,std::string&gt;::value&gt;::type&gt;
void foo( T&amp;&amp; )
{
	// Do Stuff
}
</code></pre>
<p>Soweit meine Ansätze. Evtl. gibt es auch noch eine andere? Welche von den ist sonst die zu empfehlene?</p>
<p>MfG</p>
<p>shft</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2460702</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2460702</guid><dc:creator><![CDATA[shft]]></dc:creator><pubDate>Thu, 23 Jul 2015 09:36:46 GMT</pubDate></item><item><title><![CDATA[Reply to Parameterübergabe R-Value und const-reference on Thu, 23 Jul 2015 10:13:57 GMT]]></title><description><![CDATA[<p>Nimm einfach die zweite Variante, ein move kostet dich irgendwie 4-8 instructions oder so. Jedenfalls voellig irrelevant in einem Kontext wo du gerade einen extra Thread startest. Ich wuerde die zweite Variante auch sonst fast ueberall nutzen, ausser du hast wirklich einen guten Grund es nicht zu tun.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2460711</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2460711</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Thu, 23 Jul 2015 10:13:57 GMT</pubDate></item><item><title><![CDATA[Reply to Parameterübergabe R-Value und const-reference on Thu, 23 Jul 2015 10:14:10 GMT]]></title><description><![CDATA[<p>Es gibt einen Vortrag von Herb Sutter da werden verschiedene Möglichkeiten diskutiert. Siehe hier, etwa ab Minute 55: <a href="https://www.youtube.com/watch?feature=player_detailpage&amp;v=xnqTKD8uD64#t=3300" rel="nofollow">https://www.youtube.com/watch?feature=player_detailpage&amp;v=xnqTKD8uD64#t=3300</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2460712</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2460712</guid><dc:creator><![CDATA[sebi707]]></dc:creator><pubDate>Thu, 23 Jul 2015 10:14:10 GMT</pubDate></item><item><title><![CDATA[Reply to Parameterübergabe R-Value und const-reference on Thu, 23 Jul 2015 13:46:39 GMT]]></title><description><![CDATA[<p>Danke, das Video ist echt sehr hilfreich <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/2460738</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2460738</guid><dc:creator><![CDATA[shft]]></dc:creator><pubDate>Thu, 23 Jul 2015 13:46:39 GMT</pubDate></item><item><title><![CDATA[Reply to Parameterübergabe R-Value und const-reference on Fri, 24 Jul 2015 07:50:35 GMT]]></title><description><![CDATA[<p>shft schrieb:</p>
<blockquote>
<p>Ich habe ein Thread, wobei seine Parameter beim Start kopiert bzw. verschoben werden müssen, da evtl. sonst die Lebenszeit des Threads, welcher diesen Thread startet, nicht lang genug ist. Um es dem Nutzer freizustellen, welche Version er nutzen möchte, benötige ich eine Version, die entscheidet, ob kopiert oder verschoben werden soll.</p>
</blockquote>
<p>Dafür brauchst du gar keine zwei Versionen. Das Kopieren/Moven machst nicht Du sondern der Nutzer bzw die thread-Library selbst. Der Parameter-Typ den, du für deine Funktion wählst, die du in einem neuen Thread ausführst, ist davon nahezu unabhängig.</p>
<p>shft schrieb:</p>
<blockquote>
<pre><code>void foo( const std::string&amp; s )
{
	foo( std::move( std::string( s ) ) );
}
</code></pre>
</blockquote>
<p>Das <code>std::move</code> ist hier überflüssig, da std::string(s) ja eh schon ein Rvalue ist.</p>
<p>shft schrieb:</p>
<blockquote>
<pre><code>/*
	Problem:
	Möchte ich den String in der Funktion nochmals verschieben o.Ä.,
	also muss ich nochmals std::move [...]
	*/
</code></pre>
</blockquote>
<p>Du willst also einen <code>eigenen</code> std::string in der Funktion haben? Dann nimm doch einfach</p>
<pre><code>void foo(std::string meineigenerstring) {
    …
}
</code></pre>
<p>Ob das Ding kopiert oder gemoved wird, hängt davon ab, ob der <em>Aufrufer</em> <code>std::thread</code> bzw <code>std::async</code> einen Lvalue-string oder Rvalue-string übergibt. Und da wir wissen, dass <code>std::string</code> einen sehr effizienten Move-Konstruktor hat, können wir uns hier auch die Sache mit der Überladung sparen. Das einzige, was wir uns damit sparen würden, wäre nämlich ein Move, aber der ist ja billig bei <code>std::string</code> .</p>
<p>Und auch wenn Du das hier schreibst:</p>
<pre><code>void foo(const std::string&amp; constref) {
    …
}
</code></pre>
<p>musst Du dir keine Sorgen über Lebenszeiten machen, weil bei Aufrufen wie</p>
<pre><code>std::thread (foo, std::string(&quot;temp&quot;));
</code></pre>
<p>std::thread die Argumente immer in den anderen Thread kopiert/moved. Wenn Du einem neuen Thread explizit eine Referenz übergeben willst, ginge das so:</p>
<pre><code>void foo(std::string&amp; nonconstref) {
    nonconstref = &quot;blupp&quot;;
}

int main() {
   string blah;
   std::thread t (foo, std::ref(blah));
   t.join();
   std::cout &lt;&lt; blah &lt;&lt; std::endl;
}
</code></pre>
<p>Man muss hier also extra <code>std::ref</code> hinschreiben, damit der <code>string</code> nicht gemoved oder kopiert wird.</p>
<p>Wenn Dir das nicht ganz geheuer ist, kannst du das natürlich auch per Lambda-Ausdruck machen. Dann klappt das mit der Überladung eh besser, falls Du sowas wirklich willst:</p>
<pre><code>void foo(std::string meins) {
    …
}

int main() {
   string blah = &quot;hello world&quot;;
   std::thread t ( [blah = move(blah)] { foo(move(blah)); } ); // C++14
   t.join();
}
</code></pre>
<p>Der String zieht zunächst in das Lambda-Objekt um, welches dann in den neuen Thread umzieht und dann den string weiter an foo übergibt ohne irgendwo den <code>string</code> jemals zu kopieren. Aber das ist wirklich äquivalent zu</p>
<pre><code>void foo(std::string meins) {
    …
}

int main() {
   string blah = &quot;hello world&quot;;
   std::thread t (foo, move(blah));
   t.join();
}
</code></pre>
<p>Der einzige Vorteil, den Dir hier ein Lambda-Ausdruck bietet, ist, dass Du damit besser klarkommst, wenn <code>foo</code> tatsächlich überladen wurde.</p>
<p>HTH<br />
kk</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2460785</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2460785</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Fri, 24 Jul 2015 07:50:35 GMT</pubDate></item></channel></rss>