<?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 einer Referenz]]></title><description><![CDATA[<p>Beispiel1:</p>
<pre><code>// falsche Rückgabe einer Referenz
CNumber&amp; CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber result(a+b);
    return result; // result wird zerstört, sobald das
    // Programm Sichtbarkeitsbereich von
    // operator+ verlässt
}
</code></pre>
<p>Beispiel2:</p>
<pre><code>// erneut fehlerhaft, da Zerstörung von pResult ungewiss ist
CNumber&amp; CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber *pResult = new CNumber(a+b);
    return pResult;
}
CNumber x,y,z;
CNumber sum = x+y+z; // y+z hinterlässt Speicherleck
</code></pre>
<p>Beipiel3:</p>
<pre><code>// von mir

CNumber CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber result(a + b) ;
    return result;
}
</code></pre>
<p>return ein lokal erzeugtes Object verursacht nicht zu viel kosten(Aufruf) des KopieConstructor, falls das Object sehr gross ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/136786/rückgabe-einer-referenz</link><generator>RSS for Node</generator><lastBuildDate>Sat, 29 Aug 2026 14:00:57 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/136786.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 13 Feb 2006 10:08:54 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 10:08:54 GMT]]></title><description><![CDATA[<p>Beispiel1:</p>
<pre><code>// falsche Rückgabe einer Referenz
CNumber&amp; CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber result(a+b);
    return result; // result wird zerstört, sobald das
    // Programm Sichtbarkeitsbereich von
    // operator+ verlässt
}
</code></pre>
<p>Beispiel2:</p>
<pre><code>// erneut fehlerhaft, da Zerstörung von pResult ungewiss ist
CNumber&amp; CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber *pResult = new CNumber(a+b);
    return pResult;
}
CNumber x,y,z;
CNumber sum = x+y+z; // y+z hinterlässt Speicherleck
</code></pre>
<p>Beipiel3:</p>
<pre><code>// von mir

CNumber CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    CNumber result(a + b) ;
    return result;
}
</code></pre>
<p>return ein lokal erzeugtes Object verursacht nicht zu viel kosten(Aufruf) des KopieConstructor, falls das Object sehr gross ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992879</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992879</guid><dc:creator><![CDATA[netrobot]]></dc:creator><pubDate>Mon, 13 Feb 2006 10:08:54 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 10:16:57 GMT]]></title><description><![CDATA[<p>1. dürfte klar sein, daß das nicht funktionieren kann - das Objekt wird direkt nach dem return gelöscht und die zurückgegeben Referenz zeigt ins Nirvana.</p>
<p>2. ist schonmal syntaktischer Schwachsinn - wenn du eine Referenz abgeben willst, kannst du keinen Pointer zurückgeben. Und außerdem erzeugt es das beschriebene Speicherleck.</p>
<p>3. ist nunmal in deinem Fall unumgänglich. Und viele Compiler dürften in der Lage sein, den zusätzlichen Konstruktor-Aufruf rauszuoptimieren.</p>
<p>Es gibt übrigens noch eine vierte Möglichkeit:</p>
<pre><code class="language-cpp">CNumber&amp; operator+(const CNumber&amp; a,const CNumber&amp; b)
{
  static CNumber res;
  res=a+b;
  return res;
}
</code></pre>
<p>(hat leider Probleme mit Aliasing, wenn du z.B. &quot;sum=x+y+z;&quot; aufrufst)</p>
<p>PS: Ist es eigentlich Absicht, daß dein Beispiel-Operator sich selber wieder aufruft?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992883</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992883</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Mon, 13 Feb 2006 10:16:57 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 10:44:28 GMT]]></title><description><![CDATA[<blockquote>
<p>PS: Ist es eigentlich Absicht, daß dein Beispiel-Operator sich selber wieder aufruft?</p>
</blockquote>
<p>daran habe ich nicht gedacht, ich habe nur ein Beipiel was geändert.</p>
<blockquote>
<p>ist schonmal syntaktischer Schwachsinn - wenn du eine Referenz abgeben willst, kannst du keinen Pointer zurückgeben. Und außerdem erzeugt es das beschriebene Speicherleck.</p>
</blockquote>
<p>pointer kann natürlich als Referenz zurückgeben, nur wer soll das löschen?</p>
<blockquote>
<p>hat leider Probleme mit Aliasing, wenn du z.B. &quot;sum=x+y+z;&quot; aufrufst</p>
</blockquote>
<p>das wär meine nächte Frage:</p>
<blockquote>
<p>In C++ ist es vollkommen legal, x=x; zu schreiben. Neben diesem sehr offensichtlichen Gebilde gibt es aber auch viele subtilere, die über Indirektionen auf eine Zuweisung an sich selbst hinauslaufen, sie werden als Aliasing-Problem bezeichnet und können unter Umständen gar nicht verhindert werden.<br />
Das Problem besteht darin, dass eine Zuweisung alle bisher von der linken Seite belegten Ressourcen freigeben will und danach die der rechten Seite kopiert. Genau das scheitert bei einer Zuweisung an sich selbst, die zu kopierenden Ressourcen sind gar nicht mehr vorhanden (sie wurden schließlich freigegeben).</p>
</blockquote>
<blockquote>
<p>Das Problem besteht darin, dass eine Zuweisung alle bisher von der linken Seite belegten Ressourcen freigeben will und danach die der rechten Seite kopiert.</p>
</blockquote>
<p>das verstehe ich nicht</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992910</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992910</guid><dc:creator><![CDATA[netrobot]]></dc:creator><pubDate>Mon, 13 Feb 2006 10:44:28 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 10:58:01 GMT]]></title><description><![CDATA[<p>[quote=&quot;netrobot&quot;]</p>
<blockquote>
<p>ist schonmal syntaktischer Schwachsinn - wenn du eine Referenz abgeben willst, kannst du keinen Pointer zurückgeben. Und außerdem erzeugt es das beschriebene Speicherleck.</p>
</blockquote>
<p>pointer kann natürlich als Referenz zurückgeben, nur wer soll das löschen?</p>
<blockquote></blockquote>
<p>Aber CNumber* ist trotzdem ein anderer Typ als CNumber&amp; - d.h. bei (2) müsstest du korrekterweise &quot;return *pResult;&quot; schreiben.</p>
<blockquote>
<blockquote>
<p>Das Problem besteht darin, dass eine Zuweisung alle bisher von der linken Seite belegten Ressourcen freigeben will und danach die der rechten Seite kopiert.</p>
</blockquote>
<p>das verstehe ich nicht</p>
</blockquote>
<p>Kurz gesagt - eine Zuweisung funktioniert üblicherweise in der Reihenfolge &quot;eigenen Speicher aufräumen&quot; - &quot;Daten von Quelle kopieren&quot; (andersrum hättest du ein Speicherleck, da du nach dem Kopieren nicht mehr an die alten Daten rankommst). Wenn Ziel und Quelle aber identisch sind, würde der erste Schritt auch die Daten löschen, die du im zweiten Schritt verwenden willst:</p>
<pre><code class="language-cpp">class test
{
public:
  test() : data(new int[10]) {}
  test&amp; operator=(const test&amp; other);
private:
  int* data;
};

test&amp; test::operator=(const test&amp; other);
{
  //1. Daten aufräumen
  delete[] data;
  //2. neue Daten kopieren
  data = new int[10];
  for(int i=0;i&lt;10;++i) data[i]=other.data[i];
}
</code></pre>
<p>Bis hierher sieht alles noch in Ordnung aus, aber jetzt kommt das Problem:</p>
<pre><code class="language-cpp">int main()
{
  test x;
  x=x;// BUMM
}
</code></pre>
<p>(Schritt 1 hat (ganz vorbildlich) den data-Pointer von x aufgeräumt - nur leider ist other im obigen Code das selbe Objekt und damit habe ich gerade other.data zerstört - und die nachfolgende for()-Schleife kopiert die Daten im neu angelegten Speicherblock in sich selbst)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992925</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992925</guid><dc:creator><![CDATA[CStoll (off)]]></dc:creator><pubDate>Mon, 13 Feb 2006 10:58:01 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 11:19:08 GMT]]></title><description><![CDATA[<blockquote>
<p>ber CNumber* ist trotzdem ein anderer Typ als CNumber&amp; - d.h. bei (2) müsstest du korrekterweise &quot;return *pResult;&quot; schreiben.</p>
</blockquote>
<p>dann bekomme ich eine Referenz auf ein Object, d.h. ich bekomme ein Object, in meinem Fall ist eine Referenz auf einen Zeiger, der wiederum auf ein Object zeigt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992947</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992947</guid><dc:creator><![CDATA[netrobot]]></dc:creator><pubDate>Mon, 13 Feb 2006 11:19:08 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 11:31:32 GMT]]></title><description><![CDATA[<p>netrobot schrieb:</p>
<blockquote>
<blockquote>
<p>ber CNumber* ist trotzdem ein anderer Typ als CNumber&amp; - d.h. bei (2) müsstest du korrekterweise &quot;return *pResult;&quot; schreiben.</p>
</blockquote>
<p>dann bekomme ich eine Referenz auf ein Object, d.h. ich bekomme ein Object, in meinem Fall ist eine Referenz auf einen Zeiger, der wiederum auf ein Object zeigt.</p>
</blockquote>
<p>pResult ist ein Zeiger auf ein CNumber-Objekt, *pResult IST ein CNumber-Objekt - und um eine Referenz zu initialisieren, benötigst du keinen Zeiger, sondern das Objekt auf das er zeigt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992956</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992956</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Mon, 13 Feb 2006 11:31:32 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 12:26:08 GMT]]></title><description><![CDATA[<p>das ganze geht auch schön mit templates</p>
<p><a href="http://www.flipcode.com/tutorials/tut_fastmath.shtml" rel="nofollow">http://www.flipcode.com/tutorials/tut_fastmath.shtml</a></p>
<p>rapso-&gt;greets();</p>
]]></description><link>https://www.c-plusplus.net/forum/post/992997</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/992997</guid><dc:creator><![CDATA[rapso]]></dc:creator><pubDate>Mon, 13 Feb 2006 12:26:08 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 16:55:42 GMT]]></title><description><![CDATA[<p>Returnwertoptimierung:</p>
<pre><code class="language-cpp">const CNumber CNumber::operator+(const CNumber&amp; a, const CNumber&amp; b)
{
    return result(a+b);
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/993262</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/993262</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Mon, 13 Feb 2006 16:55:42 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 18:39:17 GMT]]></title><description><![CDATA[<p>In welchem Kapitel des Standards steht das und vor allem welcher Compiler setzt das auch um <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/993344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/993344</guid><dc:creator><![CDATA[LordJaxom]]></dc:creator><pubDate>Mon, 13 Feb 2006 18:39:17 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe einer Referenz on Mon, 13 Feb 2006 21:24:18 GMT]]></title><description><![CDATA[<p>CStoll (off) schrieb:</p>
<blockquote>
<p>Kurz gesagt - eine Zuweisung funktioniert üblicherweise in der Reihenfolge &quot;eigenen Speicher aufräumen&quot; - &quot;Daten von Quelle kopieren&quot; (andersrum hättest du ein Speicherleck, da du nach dem Kopieren nicht mehr an die alten Daten rankommst). Wenn Ziel und Quelle aber identisch sind, würde der erste Schritt auch die Daten löschen, die du im zweiten Schritt verwenden willst:</p>
<pre><code class="language-cpp">class test
{
public:
  test() : data(new int[10]) {}
  test&amp; operator=(const test&amp; other);
private:
  int* data;
};

test&amp; test::operator=(const test&amp; other);
{
  //1. Daten aufräumen
  delete[] data;
  //2. neue Daten kopieren
  data = new int[10];
  for(int i=0;i&lt;10;++i) data[i]=other.data[i];
}
</code></pre>
<p>Bis hierher sieht alles noch in Ordnung aus, aber jetzt kommt das Problem:</p>
<pre><code class="language-cpp">int main()
{
  test x;
  x=x;// BUMM
}
</code></pre>
<p>(Schritt 1 hat (ganz vorbildlich) den data-Pointer von x aufgeräumt - nur leider ist other im obigen Code das selbe Objekt und damit habe ich gerade other.data zerstört - und die nachfolgende for()-Schleife kopiert die Daten im neu angelegten Speicherblock in sich selbst)</p>
</blockquote>
<p>Wobei man dazusagen sollte, dass man einen op= so niemals aufbauen sollte. Entweder man setzt den alten swap Trick ein oder achtet auf die korrekte Reihenfolge. Und das heisst, erst neuen Speicher reservieren und dann den alten freigeben. Dann funktioniert nicht nur Selbstzuweisung, der Code ist zudem exception-safe.</p>
<pre><code class="language-cpp">test&amp; test::operator=(const test&amp; other)
{
  //1. neue Daten kopieren
  tmp = new int[10];
  for(int i=0;i&lt;10;++i) tmp[i]=other.data[i];
  //2. Daten aufräumen
  delete[] data;
  data = tmp;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/993545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/993545</guid><dc:creator><![CDATA[groovemaster]]></dc:creator><pubDate>Mon, 13 Feb 2006 21:24:18 GMT</pubDate></item></channel></rss>