<?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[Rückgabe über Referenz]]></title><description><![CDATA[<p>Hi allerseits!</p>
<p>Mir scheint ich habe mehr vergessen als ich glaubte. Kann mir jemand sagen,<br />
warum Folgendes nicht ohne Warnung compliert?:</p>
<pre><code class="language-cpp">const anystring&amp; foo()
{
   return anystring(&quot;bar&quot;);
}
</code></pre>
<p>Hier sollte doch eigentlich ein temporäres String-Objekt zurück geliefert werden, in Form einer const-Referenz. Ich könnte schwören das hat früher mal funktioniert. Jedenfalls gehts nicht unter VC++2003:</p>
<pre><code>warning C4172: returning address of local variable or temporary
</code></pre>
<p>Ist daran seit neuestem irgendetwas gefährlich oder werde ich vergesslich?!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/120185/rückgabe-über-referenz</link><generator>RSS for Node</generator><lastBuildDate>Sat, 22 Aug 2026 10:54:18 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/120185.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 09 Sep 2005 17:42:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:42:43 GMT]]></title><description><![CDATA[<p>Hi allerseits!</p>
<p>Mir scheint ich habe mehr vergessen als ich glaubte. Kann mir jemand sagen,<br />
warum Folgendes nicht ohne Warnung compliert?:</p>
<pre><code class="language-cpp">const anystring&amp; foo()
{
   return anystring(&quot;bar&quot;);
}
</code></pre>
<p>Hier sollte doch eigentlich ein temporäres String-Objekt zurück geliefert werden, in Form einer const-Referenz. Ich könnte schwören das hat früher mal funktioniert. Jedenfalls gehts nicht unter VC++2003:</p>
<pre><code>warning C4172: returning address of local variable or temporary
</code></pre>
<p>Ist daran seit neuestem irgendetwas gefährlich oder werde ich vergesslich?!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868832</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868832</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:42:43 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:45:57 GMT]]></title><description><![CDATA[<p>Das Objekt wird am Ende der Funktion zerstört.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868835</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868835</guid><dc:creator><![CDATA[......]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:45:57 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:47:12 GMT]]></title><description><![CDATA[<p>Glückwunsch, du hast damit eine Methode gefunden wie man ungültige Referenzen erzeugen kann!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868837</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868837</guid><dc:creator><![CDATA[FireFlow]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:47:12 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:49:28 GMT]]></title><description><![CDATA[<p>...... schrieb:</p>
<blockquote>
<p>Das Objekt wird am Ende der Funktion zerstört.</p>
</blockquote>
<p>Naja, das ist was die Fehlermeldung impliziert. Ich war mir aber recht sicher, daß zumindest der alte GCC Compiler in der Lage war, das Temporäre Objekt lange genug zu erhalten.</p>
<p>Ich dachte jedenfalls, daß es einen Unterschied gab, zwischen</p>
<pre><code class="language-cpp">const anystring&amp; foo()
{
   return anystring(&quot;bar&quot;);
}
</code></pre>
<p>und etwas, das sicherlich noch nie funktioniert hat:</p>
<pre><code class="language-cpp">const anystring&amp; foo()
{
   anystring x(&quot;bar);

   return x;
}
</code></pre>
<p>Hat es mal Compiler gegeben, die Ersteres konnten?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868838</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868838</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:49:28 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:50:12 GMT]]></title><description><![CDATA[<p>*lol*</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868839</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868839</guid><dc:creator><![CDATA[meinung]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:50:12 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:51:11 GMT]]></title><description><![CDATA[<p>meinung schrieb:</p>
<blockquote>
<p>*lol*</p>
</blockquote>
<p>Sehr konstruktiv, prima.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868841</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868841</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:51:11 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 17:53:15 GMT]]></title><description><![CDATA[<p>Da wird nix lange erhalten... Das ist ein temporäres Objekt das wird gleich wieder gelöscht noch vor dem verlassen der Funktion.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868843</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868843</guid><dc:creator><![CDATA[FireFlow]]></dc:creator><pubDate>Fri, 09 Sep 2005 17:53:15 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 19:13:29 GMT]]></title><description><![CDATA[<p>Was Du machen kannst, ist einen Pointer zurueckzuliefern:</p>
<pre><code class="language-cpp">anystring* foo()
{
   anystring *x;

   x = new anystring (&quot;bar);

   return x;
}
</code></pre>
<p>Nur dann musst auch dafuer sorgen, dass dieser irgentwo spaeter auch wieder deleted wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868889</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868889</guid><dc:creator><![CDATA[MBCS-CITP]]></dc:creator><pubDate>Fri, 09 Sep 2005 19:13:29 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 19:14:59 GMT]]></title><description><![CDATA[<p>MBCS-CITP schrieb:</p>
<blockquote>
<p>Was Du machen kannst, ist einen Pointer zurueckzuliefern:</p>
<pre><code class="language-cpp">anystring* foo()
{
   anystring *x;

   x = new anystring (&quot;bar);

   return x;
}
</code></pre>
<p>Nur dann musst auch dafuer sorgen, dass dieser irgentwo spaeter auch wieder deleted wird.</p>
</blockquote>
<p>*lol*</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868890</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868890</guid><dc:creator><![CDATA[constructa]]></dc:creator><pubDate>Fri, 09 Sep 2005 19:14:59 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 21:15:21 GMT]]></title><description><![CDATA[<p>Jordy! Das was du machst, ist ein typischer Fehler. Das Objekt auf dem Stack existiert natürlich irgendwie weiter im Speicher, aber es ist ungültig. Und niemand kann dir versichern, das die Daten an der Speicherstelle nicht im nächsten Moment mit was anderem überschrieben wird.</p>
<pre><code class="language-cpp">int h[2] = {0,1};
std::cout &lt;&lt; h[2];
</code></pre>
<p>DAS geht auch, nur ist im dritten Feld wohl einfach etwas, was für dich ungültig ist. Klar steht da irgend ein Wert drin, nur gültig ist der trotzdem nicht.</p>
<p>Genau das gleich mit den temporären Variablen. Das hat auch nichts mit neuen oder alten GCC zu tun. Beim neuen ist es wie beim alten, nur _warnt_ dich der neue halt, was der alte einfach verseumt hatte.</p>
<p>Wenn du temp. Objekte zurück geben willst, benutz std::auto_ptr!!! Schau dazu auf meine Homepage, hab ich was zu geschrieben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868948</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868948</guid><dc:creator><![CDATA[Artchi]]></dc:creator><pubDate>Fri, 09 Sep 2005 21:15:21 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 21:18:56 GMT]]></title><description><![CDATA[<blockquote>
<p>Wenn du temp. Objekte zurück geben willst, benutz std::auto_ptr!!!</p>
</blockquote>
<p>*lol*</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868956</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868956</guid><dc:creator><![CDATA[homepage]]></dc:creator><pubDate>Fri, 09 Sep 2005 21:18:56 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 21:34:48 GMT]]></title><description><![CDATA[<p>Jordy schrieb:</p>
<blockquote>
<p>meinung schrieb:</p>
<blockquote>
<p>*lol*</p>
</blockquote>
<p>Sehr konstruktiv, prima.</p>
</blockquote>
<p>Auf (unsinnige) Beiträge von Unregs sollte man einfach nicht reagieren, EGAL was darin steht. Hab mich schon damit abgefunden und sicherlich alle anderen alten Hasen hier auch. Solltest du dir auch angewöhnen, einfach NICHT zu reagieren. <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/868960</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868960</guid><dc:creator><![CDATA[Artchi]]></dc:creator><pubDate>Fri, 09 Sep 2005 21:34:48 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 21:35:40 GMT]]></title><description><![CDATA[<p>doch <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/868961</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868961</guid><dc:creator><![CDATA[meinung]]></dc:creator><pubDate>Fri, 09 Sep 2005 21:35:40 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 22:13:06 GMT]]></title><description><![CDATA[<p>auto_ptr würd ich aber auch nicht favorisieren.</p>
<p>hier in genau diesem Fall bietet sich sogar eine tolle Möglichkeit an:</p>
<pre><code class="language-cpp">const anystring&amp; foo()
{
    static anystring str(&quot;bar&quot;);
    return str
}
</code></pre>
<p>aber: das ist kein allheilmittel da foo immer dasselbe Objekt zurückliefert. Wird str irgendwie verändert wirkt sich diese veränderung global aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868977</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868977</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Fri, 09 Sep 2005 22:13:06 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 23:01:20 GMT]]></title><description><![CDATA[<p>Wäre super, wenn du noch sagen könntest, warum du auto_ptr nicht favorisierst, obwohl du keine Alternative in der Schublade hast.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868988</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868988</guid><dc:creator><![CDATA[Artchi]]></dc:creator><pubDate>Fri, 09 Sep 2005 23:01:20 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 23:30:45 GMT]]></title><description><![CDATA[<p>ähm ich hab doch ne alternative in der Schublade <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<p>1. auto_ptr ist hier schlecht, weil er einfach nicht anständig kopiert werden kann. Es besteht hier kein Grund dafür, zu verhindern dass mehrere Zeiger auf den String zeigen. Steht dir natürlich frei, das Gegenteil zu beweisen. Bis dahin ist boost::shared_ptr meine Wahl.</p>
<p>2. es wird nach ner Referenz gefragt, und die bietest pointer als Lösungsmöglichkeit an.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868994</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868994</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Fri, 09 Sep 2005 23:30:45 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 09 Sep 2005 23:46:57 GMT]]></title><description><![CDATA[<p>und wieso nicht einfach ein anystring zurückgeben ? wenn das kopieren ein problem ist, löst man das mit move-konstruktoren und nicht mit pointern - immerhin geht das mit g++ ganz gut.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/868996</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/868996</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 09 Sep 2005 23:46:57 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Sat, 10 Sep 2005 00:00:04 GMT]]></title><description><![CDATA[<p>Erstmal danke für die Diskussion.</p>
<p>Dann bezüglich der unregistrierten Usern: Ich werde es mir zu Herzen nehmen und sie ignorieren. Schade, daß es unregistrierten erlaubt ist überhaupt zu posten. Das ist in den meisten Foren, die ich kenne, nicht so, was wohl auch der Grund ist, warum ich nicht gewöhnt bin, so behandelt zu werden.</p>
<p>Dann noch zu dem Unsinn den ich geschrieben habe. Ich habe nochmal nachgesehen. Natürlich habt ihr recht: Das funktioniert nicht und hat nie funktioniert. Ich habe das verwechselt. Aber egal. Um so länger ich nachggedacht habe, um so verwunderter bin ich, *daß* es *nicht* funktioniert. Ich versuche hinter meinen Denkfehler zu kommen. Dazu zwei Beispiele.</p>
<p>Hier nochmal mein Unsinn <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<pre><code class="language-cpp">const typ&amp; funktion1()
{
   return typ(10);
}

int main()
{
   const typ&amp; x = funktion1();
}
</code></pre>
<p>Ich habe mir gesagt, daß das temporäre Objekt innerhalb der Funktion gelöscht wird (das ist schließlich Tatsache) weil es nur innerhalb des Klassen-Scope exisitert. In der folgenden, so weit ich weiß korrekten Funktion, wird ebenfalls innerhalb der Funktion ein temporäres Objekt erzeugt, das außerhalb des Funktionsaurufes weiter existiert (sonst könnte es nicht als Rückgabewert dienen):</p>
<pre><code class="language-cpp">const typ funktion2()
{
   return typ(10);
}
</code></pre>
<p>Das ist also irgendwie nicht das schlagende Argument, denn offenbar kann ein temporäres Objekt doch weiterexistieren.<br />
Dann habe ich mir gesagt, daß das temporäre Objekt, wenn es über eine Referenz zurückgegeben werden soll, ja erst einer Art temporären Referenz zugewiesen wird, bevor es dann der endgültigen Referenz (im Beispiel &quot;x&quot;) zugewiesen wird. Aber auch das ist kein Problem, denn ein temporäres Objekt existiert solange, wie die Referenz, die auf es verweist. Zumindest ist das im folgenden Fall so:</p>
<pre><code class="language-cpp">void main()
{
   const typ &amp;y = funktion2();

} // das temporäre objekt von funktion2() wird erst hier vernichtet
</code></pre>
<p>Also, wo ist mein Denkfehler? Wie hätte ich mir herleiten können, daß die funktion1() Blödsinn ist, ohne den speziellen Fall zu kennen oder auszuprobieren?</p>
<p>Achja, wo ich gerade dabei bin mich zu blamieren... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /><br />
Ich habe noch so einen Denkfehler, den mir offenbar kein Buch erklären kann. Folgendes:</p>
<pre><code class="language-cpp">class a
{
public:
   a(int x) : member(x) {}
   int member;
};

void main()
{
   a var2(10);  // Fall 1
   a var1 = 10; // Fall 2
}
</code></pre>
<p>Das funktioniert einwandfrei. In beiden Fällen wird völlig korrekt der int-Konstruktor aufgerufen. Ich habe auch extra noch einige Tests mit überladenen copy-Konstruktoren und Zuweisungsoperatoren gemacht, um sicher zu sein, daß ich keinen Denkfehler mache und keinerlei implizite Aufrufe stattfinden. Die beiden Fälle sind hier offenbar völlig äquivalent (das war es zumindest, was ich immer dachte).</p>
<p>Nun habe ich folgendes gemacht:</p>
<pre><code class="language-cpp">class a
{
public:
   explicit a(int x) : member(x) {}
   int member;
};

void main()
{
   a var1(10);  // Fall 1
   a var2 = 10; // Fall 2 -&gt; Fehler
}
</code></pre>
<p>Jetzt knallt es. Um es vorweg zu nehmen: daß hier ein Fehler auftreten würde, war mir völlig klar. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f576.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--sunglasses"
      title=":sunglasses:"
      alt="🕶"
    /><br />
Nur das *Warum* nicht. Und alle Quellen die ich prüfen konnte, haben sich darüber ausgeschweigen.<br />
&quot;Plötzlich&quot; behauptet der Compiler, was vorher völlig korrekt funktioniert hat, wäre jetzt illegal. Er sagt sogar, daß der Fall 2 eine implizite Konvertierung beinhalten würde. Und genau das verstehe ich nicht. Wenn der Compiler im ersten Fall offenbar keine impliziten Konvertierungen gemacht hat, warum sollte er (*mit* dem explicit Schlüsselwort) plötzlich doch eine brauchen? Immerhin soll 'explicit' implizite Konvertierungen verbieten, aber doch nicht *erzeugen*?! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Das gleiche passiert bei Verwendung eines Auto-Pointers (dessen Konstruktoren ja auch explizit sind) und einer Zuweisung von 'new':</p>
<pre><code class="language-cpp">class a
{
public:
   explicit a(int x) : member(x) {}
   int member;
};

void main()
{
   auto_ptr&lt;a&gt; var1 = new a(10); // Fall 1 -&gt; Fehler
   auto_ptr&lt;a&gt; var2(new a(10));  // Fall 2
}
</code></pre>
<p>Auch hier wußte ich, daß es einen Unterschied gibt, konnte aber nirgends eine Erklärung finden, *warum* die beiden Fälle sich unterschieden.</p>
<p>Mögen jetzt manche sagen: Ist doch egal, Hauptsache man weiß *wie* es geht, aber mich wurmt das. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f621.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--pouting_face"
      title=":rage:"
      alt="😡"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/869001</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/869001</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Sat, 10 Sep 2005 00:00:04 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Sat, 10 Sep 2005 08:56:35 GMT]]></title><description><![CDATA[<p>Jordy schrieb:</p>
<blockquote>
<p>Hier nochmal mein Unsinn <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /></p>
<pre><code class="language-cpp">const typ&amp; funktion1()
{
   return typ(10);
}

int main()
{
   const typ&amp; x = funktion1();
}
</code></pre>
<p>Ich habe mir gesagt, daß das temporäre Objekt innerhalb der Funktion gelöscht wird (das ist schließlich Tatsache) weil es nur innerhalb des Klassen-Scope exisitert. In der folgenden, so weit ich weiß korrekten Funktion, wird ebenfalls innerhalb der Funktion ein temporäres Objekt erzeugt, das außerhalb des Funktionsaurufes weiter existiert (sonst könnte es nicht als Rückgabewert dienen):</p>
<pre><code class="language-cpp">const typ funktion2()
{
   return typ(10);
}
</code></pre>
</blockquote>
<p>In der ersten Version gibst du eine Referenz auf das lokale Objekt zurück. In der zweiten Version wird ein *Kopie* des lokalen Objekts erzeugt. Das sind zwei völlig verschiedene Paar Schuhe.</p>
<p>Jordy schrieb:</p>
<blockquote>
<p>Ich habe noch so einen Denkfehler, den mir offenbar kein Buch erklären kann. Folgendes:</p>
<pre><code class="language-cpp">class a
{
public:
   a(int x) : member(x) {}
   int member;
};

void main()
{
   a var2(10);  // Fall 1
   a var1 = 10; // Fall 2
}
</code></pre>
<p>Das funktioniert einwandfrei. In beiden Fällen wird völlig korrekt der int-Konstruktor aufgerufen. Ich habe auch extra noch einige Tests mit überladenen copy-Konstruktoren und Zuweisungsoperatoren gemacht, um sicher zu sein, daß ich keinen Denkfehler mache und keinerlei implizite Aufrufe stattfinden. Die beiden Fälle sind hier offenbar völlig äquivalent (das war es zumindest, was ich immer dachte).</p>
</blockquote>
<p>Äquivalent im Verhalten, aber nicht identisch.<br />
Den Unterschied habe ich hier erklärt: <a href="http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&amp;faq=copyvsdirect#Answ" rel="nofollow">http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&amp;faq=copyvsdirect#Answ</a></p>
<p>Jordy schrieb:</p>
<blockquote>
<p>Nun habe ich folgendes gemacht:</p>
<pre><code class="language-cpp">class a
{
public:
   explicit a(int x) : member(x) {}
   int member;
};

void main()
{
   a var1(10);  // Fall 1
   a var2 = 10; // Fall 2 -&gt; Fehler
}
</code></pre>
<p>Jetzt knallt es. Um es vorweg zu nehmen: daß hier ein Fehler auftreten würde, war mir völlig klar. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f576.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--sunglasses"
      title=":sunglasses:"
      alt="🕶"
    /><br />
Nur das *Warum* nicht.</p>
</blockquote>
<p>Weil das die Bedeutung von explicit ist.<br />
Im zweiten Fall passiert (theoretisch) folgendes:<br />
1. Aus dem Integer 10 wird in ein temporäres X-Objekt erzeugt (implizite Konvertierung von int nach a).<br />
2. Das temporäre X-Objekt wird über den Copy-Ctor für die Erzeugung von var2 verwendet.</p>
<p>Erstens erfordert eine implizite Konvertierung von a nach int. Für eine solche implizite Konvertierung kommen zwei Konstrukte in Frage. Entweder ein Konstruktor der sich mit einem Argument aufrufen lässt oder aber ein Konvertierungsoperator. Letzterer fällt weg, da int keine Klasse ist und somit keinen Konvertierungsoperator nach a haben kann. Bleibt der Ein-Parameter-Konstruktor.<br />
Ein solcher wird aber nur für implizite Konvertierungen verwendet, wenn er *nicht* als explicit deklariert wurde. explicit sorgt also dafür, dass ein so deklarierter Konstruktor niemals für implizite Konvertierungen verwendet wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/869057</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/869057</guid><dc:creator><![CDATA[HumeSikkins]]></dc:creator><pubDate>Sat, 10 Sep 2005 08:56:35 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Sat, 10 Sep 2005 20:59:11 GMT]]></title><description><![CDATA[<p>HumeSikkins schrieb:</p>
<blockquote>
<p>In der ersten Version gibst du eine Referenz auf das lokale Objekt zurück. In der zweiten Version wird ein *Kopie* des lokalen Objekts erzeugt. Das sind zwei völlig verschiedene Paar Schuhe.</p>
</blockquote>
<p>Hm. Wenn dem so ist (das hatte ich auch mal vermutet) dann tut das aber wohl keiner Compiler in der Realität. Auch nicht unter Deaktivierung aller Optimierungen. Jedenfalls - auch wenn es kein Compiler in der Realität macht - ist das natürlich die Erklärung.</p>
<p>HumeSikkins schrieb:</p>
<blockquote>
<p>Äquivalent im Verhalten, aber nicht identisch.<br />
Den Unterschied habe ich hier erklärt: <a href="http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&amp;faq=copyvsdirect#Answ" rel="nofollow">http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&amp;faq=copyvsdirect#Answ</a></p>
</blockquote>
<p>HumeSikkins schrieb:</p>
<blockquote>
<p>Weil das die Bedeutung von explicit ist.<br />
Im zweiten Fall passiert (theoretisch) folgendes:<br />
1. Aus dem Integer 10 wird in ein temporäres X-Objekt erzeugt (implizite Konvertierung von int nach a).<br />
2. Das temporäre X-Objekt wird über den Copy-Ctor für die Erzeugung von var2 verwendet.</p>
</blockquote>
<p>Ahja. Dann wird dieser Fall in diversen Beschreibungen aber mächtig vereinfacht. Ich habe nämlich mehrfach gelesen, daß beide Fälle einem Aufruf des Konstruktors auf den rechten Ausdruck entsprechen. Der Copy-Konstruktor wurde nicht erwähnt. Da auch Compiler genau diesen Code produzieren, habe ich das nicht in Frage gestellt. Auch hier läuft bei den Compilern wohl eine Art von Optimierung, die sich nicht abstellen läßt. Jedenfalls ist mir jetzt auch der Rest klar.</p>
<p>Trotzdem frage ich mich, warum der Sprachstandard das so definiert. Immerhin hätte man doch auch problemlos sagen können, daß auch eine Initalisierung mit '=' grundsätzlich den passenden Konstruktor aufruft (falls vorhanden), also wirklich *identisch* ist. Das hätte doch genau so funktioniert und die leidige Einschränkung, die '=' Syntax bei expliciten Konstruktoren nicht verwenden zu können, wäre weggefallen, oder? Und der Copy-Konstruktor-Fall wäre wirklich nur noch dann zum Tragen gekommen, wenn schon ein Objekt des gleichen Typs vorliegt.</p>
<p>Achja, danke für deine erfreulich sachlichen Erläuterungen, das hat nicht jeder hier geschafft <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>
]]></description><link>https://www.c-plusplus.net/forum/post/869408</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/869408</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Sat, 10 Sep 2005 20:59:11 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Sun, 11 Sep 2005 09:07:56 GMT]]></title><description><![CDATA[<p>Jordy schrieb:</p>
<blockquote>
<p>HumeSikkins schrieb:</p>
<blockquote>
<p>In der ersten Version gibst du eine Referenz auf das lokale Objekt zurück. In der zweiten Version wird ein *Kopie* des lokalen Objekts erzeugt. Das sind zwei völlig verschiedene Paar Schuhe.</p>
</blockquote>
<p>Hm. Wenn dem so ist (das hatte ich auch mal vermutet) dann tut das aber wohl keiner Compiler in der Realität. Auch nicht unter Deaktivierung aller Optimierungen. Jedenfalls - auch wenn es kein Compiler in der Realität macht - ist das natürlich die Erklärung.</p>
</blockquote>
<p>Die Optimierung die hier durchgeführt wird, nennt sich Return-Value-Optimization (RVO). Der Punkt ist auch hier, dass der Copy-Ctor zugreifbar sein muss, selbst wenn der Compiler den eigentlichen Kopiervorgang wegoptimiert.</p>
<p>Der folgende Code ist z.B. illegal, nichtsdestotrotz wird er von einigen Compilern übersetzt:</p>
<pre><code class="language-cpp">class Typ {
public:
   Typ(int);
private
   // Achtung: Copy-Ctor ist private
   // Typ kann niemals by-value returned werden
   Typ(const Typ&amp;);
};

const Typ func() {
    return Typ(10); // Illegal, selbst wenn Compiler 
                    // die Kopie eleminiert.
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/869506</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/869506</guid><dc:creator><![CDATA[HumeSikkins]]></dc:creator><pubDate>Sun, 11 Sep 2005 09:07:56 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe über Referenz on Fri, 16 Sep 2005 10:30:52 GMT]]></title><description><![CDATA[<p>HumeSikkins schrieb:</p>
<blockquote>
<p>Jordy schrieb:</p>
<blockquote>
<p>HumeSikkins schrieb:</p>
<blockquote>
<p>In der ersten Version gibst du eine Referenz auf das lokale Objekt zurück. In der zweiten Version wird ein *Kopie* des lokalen Objekts erzeugt. Das sind zwei völlig verschiedene Paar Schuhe.</p>
</blockquote>
<p>Hm. Wenn dem so ist (das hatte ich auch mal vermutet) dann tut das aber wohl keiner Compiler in der Realität. Auch nicht unter Deaktivierung aller Optimierungen. Jedenfalls - auch wenn es kein Compiler in der Realität macht - ist das natürlich die Erklärung.</p>
</blockquote>
<p>Die Optimierung die hier durchgeführt wird, nennt sich Return-Value-Optimization (RVO). Der Punkt ist auch hier, dass der Copy-Ctor zugreifbar sein muss, selbst wenn der Compiler den eigentlichen Kopiervorgang wegoptimiert.</p>
<p>Der folgende Code ist z.B. illegal, nichtsdestotrotz wird er von einigen Compilern übersetzt:</p>
<pre><code class="language-cpp">class Typ {
public:
   Typ(int);
private
   // Achtung: Copy-Ctor ist private
   // Typ kann niemals by-value returned werden
   Typ(const Typ&amp;);
};

const Typ func() {
    return Typ(10); // Illegal, selbst wenn Compiler 
                    // die Kopie eleminiert.
}
</code></pre>
</blockquote>
<p>Ok, danke. Ist jetzt alles klar.<br />
Und zudem habe ich gelernt, mich mit Sicherheit nicht mehr auf das Verhalten von konkreten Compiler zu stützen. Naja, eigentlich eine Weisheit die man kennt...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/873580</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/873580</guid><dc:creator><![CDATA[Jordy]]></dc:creator><pubDate>Fri, 16 Sep 2005 10:30:52 GMT</pubDate></item></channel></rss>