<?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[Zugriffsverweigerung bei Destruktor]]></title><description><![CDATA[<p>Hallo zusammen, ich bin gerade dran, ein kleines Spiel zu schreiben.<br />
Jetzt bin ich vor einem Problem stehen geblieben, das ich bis jetzt noch nie hatte (hatte auch noch nicht viel mit Destruktoren zu tun).</p>
<p>Ich habe eine Klasse für Gegner, von denen haben einige ein schwenkbares Kanonenrohr. Weil nur einige und nicht alle ein solches besitzen, dachte ich, es wäre Speicherverschwendung, es als Member in die Klasse zu schreiben, deshalb hab ich nur den Zeiger gemacht (nur relevante Member sind aufgelistet):</p>
<pre><code class="language-cpp">class Enemy : public sf::Sprite
{
	private:
		sf::Sprite *Barrel;
	public:
		Enemy(...); // besitzt einige Argumente betreffend Position etc.
		~Enemy();
		sf::Sprite GetBarrel(); // Wenn man von aussen auf das Rohr zugreifen will, mit dieser Funktion (by reference)
};
</code></pre>
<p>Im Konstruktor wird dem Barrel entweder ein Nullzeiger (wenn der Gegner kein Rohr besitzt) oder ein sf::Sprite zugewiesen:</p>
<pre><code class="language-cpp">Enemy::Enemy(...)
{
    // ...
	if (/*Gegner hat ein Rohr*/)
	    Barrel = new sf::Sprite(Image);
	else
		Barrel = NULL;
}
</code></pre>
<p>Der Destruktor löscht das dynamische Rohr wieder (wie ich gehört habe, macht es nichts, Nullzeiger zu deleten):</p>
<pre><code class="language-cpp">Enemy::~Enemy()
{
    delete Barrel;
}
</code></pre>
<p>Hier, beim delete-Befehl, tritt die Zugriffsverletzung auf. Dazu müsste doch ein Zeiger falsch oder nicht initialisiert worden sein, und das ist nach meinem Konstruktor anscheinend nicht möglich, oder? Wenn ich mir jedoch die Zeigeradresse ausgeben lasse (std::cout &lt;&lt; Barrel &lt;&lt; std::endl;), ohne zu deleten, geht alles.</p>
<p>Was vielleicht noch erwähnenswert ist: Die Klasse Enemy ist wiederum Bestandteil einer anderen Klasse Map, und zwar als std::vector&lt;Enemy&gt;. Einzelne Gegner werden mit erase gelöscht, dann sollte der Destruktor eigentlich zum Zuge kommen. Ohne das delete im Destruktor habe ich nie Probleme.</p>
<p>Ich habe die anderen Beiträge mit ähnlichem Thema gelesen, kann die Lösung jedoch nicht auf mein Problem anwenden.</p>
<p>Edit: Was mir gerade noch eingefallen ist: Könnte es damit zusammenhängen, dass die Klasse selber eine Variable besitzt, die den selben Typ hat wie die Basisklasse (Enemy wurde von sf::Sprite abgeleitet)?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/209843/zugriffsverweigerung-bei-destruktor</link><generator>RSS for Node</generator><lastBuildDate>Tue, 13 Oct 2026 02:22:04 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/209843.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 03 Apr 2008 22:38:40 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Thu, 03 Apr 2008 22:42:05 GMT]]></title><description><![CDATA[<p>Hallo zusammen, ich bin gerade dran, ein kleines Spiel zu schreiben.<br />
Jetzt bin ich vor einem Problem stehen geblieben, das ich bis jetzt noch nie hatte (hatte auch noch nicht viel mit Destruktoren zu tun).</p>
<p>Ich habe eine Klasse für Gegner, von denen haben einige ein schwenkbares Kanonenrohr. Weil nur einige und nicht alle ein solches besitzen, dachte ich, es wäre Speicherverschwendung, es als Member in die Klasse zu schreiben, deshalb hab ich nur den Zeiger gemacht (nur relevante Member sind aufgelistet):</p>
<pre><code class="language-cpp">class Enemy : public sf::Sprite
{
	private:
		sf::Sprite *Barrel;
	public:
		Enemy(...); // besitzt einige Argumente betreffend Position etc.
		~Enemy();
		sf::Sprite GetBarrel(); // Wenn man von aussen auf das Rohr zugreifen will, mit dieser Funktion (by reference)
};
</code></pre>
<p>Im Konstruktor wird dem Barrel entweder ein Nullzeiger (wenn der Gegner kein Rohr besitzt) oder ein sf::Sprite zugewiesen:</p>
<pre><code class="language-cpp">Enemy::Enemy(...)
{
    // ...
	if (/*Gegner hat ein Rohr*/)
	    Barrel = new sf::Sprite(Image);
	else
		Barrel = NULL;
}
</code></pre>
<p>Der Destruktor löscht das dynamische Rohr wieder (wie ich gehört habe, macht es nichts, Nullzeiger zu deleten):</p>
<pre><code class="language-cpp">Enemy::~Enemy()
{
    delete Barrel;
}
</code></pre>
<p>Hier, beim delete-Befehl, tritt die Zugriffsverletzung auf. Dazu müsste doch ein Zeiger falsch oder nicht initialisiert worden sein, und das ist nach meinem Konstruktor anscheinend nicht möglich, oder? Wenn ich mir jedoch die Zeigeradresse ausgeben lasse (std::cout &lt;&lt; Barrel &lt;&lt; std::endl;), ohne zu deleten, geht alles.</p>
<p>Was vielleicht noch erwähnenswert ist: Die Klasse Enemy ist wiederum Bestandteil einer anderen Klasse Map, und zwar als std::vector&lt;Enemy&gt;. Einzelne Gegner werden mit erase gelöscht, dann sollte der Destruktor eigentlich zum Zuge kommen. Ohne das delete im Destruktor habe ich nie Probleme.</p>
<p>Ich habe die anderen Beiträge mit ähnlichem Thema gelesen, kann die Lösung jedoch nicht auf mein Problem anwenden.</p>
<p>Edit: Was mir gerade noch eingefallen ist: Könnte es damit zusammenhängen, dass die Klasse selber eine Variable besitzt, die den selben Typ hat wie die Basisklasse (Enemy wurde von sf::Sprite abgeleitet)?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486119</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486119</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Thu, 03 Apr 2008 22:42:05 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Thu, 03 Apr 2008 22:57:21 GMT]]></title><description><![CDATA[<p>copy-konstruktor und zuweisungsoperator sind definiert?<br />
in einem <code>vector&lt;Enemy&gt;</code> werden nämlich nur kopien gespeichert. und compilergenerierte copy-konstruktoren beherrschen tiefe kopien nicht - d.h. wenn du eine kopie eines Enemys erstellst - du also zwei Enemys hast - versucht der konstruktor jeweils, dasselbe Rohr zu löschen. zweimal delete auf dieselbe speicherstelle, das tut weh.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486122</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486122</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Thu, 03 Apr 2008 22:57:21 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 00:02:00 GMT]]></title><description><![CDATA[<p>Nein, den hab ich nicht (hab neben diesem Enemy-Konstruktor keinen andern für die Klasse mehr). Bis jetzt bin ich immer schön ohne Kopierkonstruktor ausgekommen.</p>
<p>Wäre das einfach so (mit entsprechender Deklaration):</p>
<pre><code class="language-cpp">Enemy::Enemy(const Enemy &amp;NewEnemy)
{
   Barrel = new sf::Sprite(Image);
}
</code></pre>
<p>Aber sobald ich den Kopierkonstruktor verwende, muss ich doch alle Variabeln der Klasse manuell kopieren, oder gibt es eine Möglichkeit, nur einzelne manuell handzuhaben? Ich hätte sonst eine riesige Zuweisungsliste...</p>
<p>Ausserdem, einige Zuweisungen funktionieren gar nicht (wegen der Referenz glaube ich). Wie müsste ich es innerhalb des Kopierkonstruktors schreiben, um z.B. Folgendes zu tun:</p>
<pre><code class="language-cpp">Type = NewEnemy.GetType();
</code></pre>
<p>wobei GetType eine short-Variable zurückgibt:</p>
<pre><code class="language-cpp">Enemy::GetType()
{
   return Type; // Type ist vom Typ short int
}
</code></pre>
<p>Ich erhalte immer eine Fehlermeldung: <em>error C2662: 'Enemy::GetType': this-Zeiger kann nicht von 'const Enemy' in 'Enemy &amp;' konvertiert werden</em></p>
<p>Und da muss ich doch noch einen separaten, zweiten Destruktor machen, oder? Was würde dann in dem stehen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486136</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486136</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 00:02:00 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 00:12:04 GMT]]></title><description><![CDATA[<p>Ja, dein Copy-Ctor würde in etwa so aussehen. Du musst dich einfach fragen was du alles machen musst, um von dem übergebenen Parameter eine Kopie zu erzeugen. Bei Pointern musst du also Speicher anfordern und initialisieren und alles andere einfach mittels des Parameters kopieren. Im Grunde also immer ein this-&gt;foo = parameter-&gt;foo;</p>
<p>Die Fehlermeldung bekommst du, weil deine Referenz konstant ist, GetType jedoch nicht. Mach entweder GetType const oder greif direkt auf Type zu (also NewEnemy.Type)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486137</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486137</guid><dc:creator><![CDATA[this-*gt*that]]></dc:creator><pubDate>Fri, 04 Apr 2008 00:12:04 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 00:21:39 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Nein, den hab ich nicht (hab neben diesem Enemy-Konstruktor keinen andern für die Klasse mehr). Bis jetzt bin ich immer schön ohne Kopierkonstruktor ausgekommen.</p>
<p>Wäre das einfach so (mit entsprechender Deklaration):</p>
<pre><code class="language-cpp">Enemy::Enemy(const Enemy &amp;NewEnemy)
{
   Barrel = new sf::Sprite(Image);
}
</code></pre>
</blockquote>
<p>statt einer zuweisung solltest du in konstruktoren immer die elementinitialisierungsliste verwenden:</p>
<pre><code class="language-cpp">Enemy::Enemy(const Enemy&amp; NewEnemy)
: Barrel(new sf::Sprite(Image))
{
}
</code></pre>
<p>wenn du mehr als einen member dynamisch per new initialisierst, ist die &quot;länge&quot; des copy-ctors außerdem noch dein geringstes problem:</p>
<pre><code class="language-cpp">class Foo
{
   int *a, *b;
public:
   Foo (Foo const&amp; other)
   : a(new int(other.a)), b(new int(other.b))
   { 
   }
};
</code></pre>
<p>falls <code>new int(other.b)</code> fehlschlägt, wer löscht dann <code>new int(other.a)</code> ?<br />
eventuell könntest du an dieser stelle auch überlegen, smart-pointer zu verwenden. allerdings möchte ich dir nicht in deinem design rumpfuschen, dafür weiß ich zuwenig über deine anforderungen.</p>
<blockquote>
<p>Ausserdem, einige Zuweisungen funktionieren gar nicht (wegen der Referenz glaube ich). Wie müsste ich es innerhalb des Kopierkonstruktors schreiben, um z.B. Folgendes zu tun:</p>
<pre><code class="language-cpp">Type = NewEnemy.GetType();
</code></pre>
<p>wobei GetType eine short-Variable zurückgibt:</p>
<pre><code class="language-cpp">Enemy::GetType()
{
   return Type; // Type ist vom Typ short int
}
</code></pre>
<p>Ich erhalte immer eine Fehlermeldung: <em>error C2662: 'Enemy::GetType': this-Zeiger kann nicht von 'const Enemy' in 'Enemy &amp;' konvertiert werden</em></p>
</blockquote>
<p>ganz einfach, die methode <code>Enemy::GetType</code> konstant machen, wie this-&gt;that schon vorgeschlagen hat.<br />
das geht so:</p>
<pre><code class="language-cpp">class Enemy
{
//...
   short GetType () const
   { 
      return Type;
   }
};
</code></pre>
<blockquote>
<p>Und da muss ich doch noch einen separaten, zweiten Destruktor machen, oder? Was würde dann in dem stehen?</p>
</blockquote>
<p>eine klasse kann nur einen destruktor haben. was meinst du also?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486138</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486138</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Fri, 04 Apr 2008 00:21:39 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 00:48:04 GMT]]></title><description><![CDATA[<p>Okay, ich dachte, es läge an der Referenz, zumal in der Fehlermeldung auch Enemy mit Enemy&amp; verglichen wird. Merkwürdig, dass <em>const short GetType()</em> nicht geht, <em>short GetType() const</em> aber schon... Ich dachte, das spiele keine Rolle.</p>
<p>Aber wieso muss <em>GetType()</em> konstant sein? Beim direkten Zugriff wäre ja <em>Type</em> auch nicht konstant, oder? Wenn wir gerade dabei sind, was ist genau der Unterschied zwischen <em>short GetType() const</em> und <em>short GetType()</em>? Die nicht-konstante Version kann ja auch nicht verändert werden (kein L-Value).</p>
<p>queer_boy schrieb:</p>
<blockquote>
<p>wenn du mehr als einen member dynamisch per new initialisierst, ist die &quot;länge&quot; des copy-ctors außerdem noch dein geringstes problem:</p>
<pre><code class="language-cpp">class Foo
{
   int *a, *b;
public:
   Foo (Foo const&amp; other)
   : a(new int(other.a)), b(new int(other.b))
   { 
   }
};
</code></pre>
<p>falls <code>new int(other.b)</code> fehlschlägt, wer löscht dann <code>new int(other.a)</code> ?<br />
eventuell könntest du an dieser stelle auch überlegen, smart-pointer zu verwenden. allerdings möchte ich dir nicht in deinem design rumpfuschen, dafür weiß ich zuwenig über deine anforderungen.</p>
</blockquote>
<p>Okay, das wäre dann wohl schon zu kompliziert (noch nie von Smart-Pointern gehört), da würde es sich fast eher lohnen, Barrel nicht als Zeiger zu verwenden, sondern als normale Variable. Trotzdem danke, vielleicht werde ich das später mal berücksichtigen... Aber wieso sollte das new überhaupt fehlschlagen?</p>
<p>queer_boy schrieb:</p>
<blockquote>
<blockquote>
<p>Und da muss ich doch noch einen separaten, zweiten Destruktor machen, oder? Was würde dann in dem stehen?</p>
</blockquote>
<p>eine klasse kann nur einen destruktor haben. was meinst du also?</p>
</blockquote>
<p>Sorry, da hab ich was falsch verstanden, ich dachte ich müsste den im Kopierkonstruktor per new sf::Sprite definierten Zeiger auch noch deleten, aber das wird wohl schon im (einzigen) Destruktor getan...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486142</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486142</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 00:48:04 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 01:38:28 GMT]]></title><description><![CDATA[<p>bei einer membermethode wird auch (implizit) der this-zeiger übergeben. tatsächlich sieht der aufruf einer member-funktion dann so aus (in C):</p>
<pre><code class="language-cpp">struct Enemy
{
   short Type;
};

short GetType (Enemy* this)
{
  return this-&gt;Type;
}

Enemy x;
GetType (&amp;x);
//und das ist äquivalent zu (C++) x.GetType();
</code></pre>
<p>das problem ist nun, dass es sehr wohl auch konstante Enemy-objekte geben kann (oder zeiger darauf). das wäre kein problem, wenn man GetType einfach für konstante Enemy-objekte überladen könnte:</p>
<pre><code class="language-cpp">short GetType (const Enemy* this)
{
   return this-&gt;Type;
}
</code></pre>
<p>genau das erlaubt die C++-syntax auf diese art und weise:</p>
<pre><code class="language-cpp">class Enemy
{
public:
   short GetType () const; //this zeigt auf const Enemy
   short GetType (); //this zeigt auf Enemy (non-const)
};
</code></pre>
<p>tatsächlich lassen sich von einer (member)funktion sowohl konstante als auch nicht-konstante versionen definieren (also überladen).</p>
<p>da du in deinem copy-ctor eine referenz auf ein konstantes Enemy hast, kannst du für dieses Enemy auch nur konstante memberfunktionen aufrufen.</p>
<blockquote>
<p>Aber wieso sollte das new überhaupt fehlschlagen?</p>
</blockquote>
<p>in diesem fall würde new nur fehlschlagen können, wenn es keinen speicher mehr gibt. selten, aber doch möglich.<br />
anders sieht es schon aus, wenn du benutzerdefinierte klassen verwendest (und nicht wie in meinem beispiel ints), deren konstruktor eine ausnahme wirft:</p>
<pre><code class="language-cpp">class Naughty
{
public:
   Naughty (int x)
   {
     if (x != 42) throw &quot;this is not the answer!&quot;;
   }
};

class Enemy
{
   Naughty *n, *m;
public:
   Enemy () : n(new Naughty(42)), m(new Naughty(23)) {}
};

try
{
 Enemy e;
} catch (...) 
{
}
</code></pre>
<p>schwupps, schon hast du ein memory-leak, und das ist oft nicht so einfach zurückzuverfolgen.</p>
<p>lies dir dazu einfach mal was über smart-pointer und exception safety durch <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/1486144</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486144</guid><dc:creator><![CDATA[queer_boy]]></dc:creator><pubDate>Fri, 04 Apr 2008 01:38:28 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 06:54:55 GMT]]></title><description><![CDATA[<p>queer_boy schrieb:</p>
<blockquote>
<p>statt einer zuweisung solltest du in konstruktoren immer die elementinitialisierungsliste verwenden:</p>
<pre><code class="language-cpp">Enemy::Enemy(const Enemy&amp; NewEnemy)
: Barrel(new sf::Sprite(Image))
{
}
</code></pre>
<p>wenn du mehr als einen member dynamisch per new initialisierst, ist die &quot;länge&quot; des copy-ctors außerdem noch dein geringstes problem:</p>
<pre><code class="language-cpp">class Foo
{
   int *a, *b;
public:
   Foo (Foo const&amp; other)
   : a(new int(other.a)), b(new int(other.b))
   { 
   }
};
</code></pre>
<p>falls <code>new int(other.b)</code> fehlschlägt, wer löscht dann <code>new int(other.a)</code> ?</p>
</blockquote>
<p>genau wegen solcher Dinge gehören news für normale pointer <strong>nicht</strong> in die Initialisierungsliste. Wenn innerhalb der Initialisierungsliste eine Exception ausgelöst wird, hat man sich sofort ein Speicherleck eingehandelt. Selbst im Ctor Body muss man dann noch mit einem lokalen try/catch Block fehlgeschlagene news abfangen. Deshalb bei lebenswichtigen Pointermembern lieber gleich smartpointer verwenden.<br />
Mehr zum Thema: <a href="http://www.gotw.ca/gotw/066.htm" rel="nofollow">http://www.gotw.ca/gotw/066.htm</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486191</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486191</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Fri, 04 Apr 2008 06:54:55 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 09:09:18 GMT]]></title><description><![CDATA[<p>pumuckl schrieb:</p>
<blockquote>
<p>...<br />
Mehr zum Thema: <a href="http://www.gotw.ca/gotw/066.htm" rel="nofollow">http://www.gotw.ca/gotw/066.htm</a></p>
</blockquote>
<p>ebenda schrieb:</p>
<blockquote>
<p>...<br />
The short answer is: By using a function-try-block.</p>
<p>For example, here's how we can write a function-try-block for C's constructor:</p>
<pre><code class="language-cpp">// Example 1(a): Constructor function-try-block
    //
    C::C()
    try
      : A ( /*...*/ ) // optional initialization list
      , b_( /*...*/ )
    {
    }
    catch( ... )
    {
      // We get here if either A::A() or B::B() throws.

      // If A::A() succeeds and then B::B() throws, the
      // language guarantees that A::~A() will be called
      // to destroy the already-created A base subobject
      // before control reaches this catch block.
    }
</code></pre>
</blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /><br />
Wieder mal bestätigt sich &quot;Man lernt nie aus&quot; !!!<br />
Von der Konstruktion hatte ich noch nie gehört.</p>
<p>Gleich ausprobiert (g++ 3.3.3) und (für mich) Erstaunliches festgestellt: Dieser catch-Block &quot;fängt&quot; zwar die Exception, sie fliegt danach aber trotzdem weiter.</p>
<p>Wie auc hier steht:</p>
<blockquote>
<p>... What's less obvious, but clearly stated in the standard, is that if the catch block does not throw ... and control reaches the end of the catch block of a constructor or destructor, then the original exception is automatically rethrown.</p>
</blockquote>
<p>da muss ich nochmal ein wenig mit rumspielen und -lesen.<br />
<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="👍"
    /> <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="😋"
    /></p>
<p>Danke,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486277</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486277</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Fri, 04 Apr 2008 09:09:18 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 10:50:13 GMT]]></title><description><![CDATA[<p>Vielen Dank für die zahlreichen Antworten! Ich hätte nicht gedacht, dass wegen eines einzigen Zeigers ein solcher Mehraufwand erforderlich ist <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="😉"
    /><br />
Aber das ist sowieso gerade eine gute Übung für mich, zumal ich bis jetzt noch nicht viel von Kopierkonstruktor, konstanten Funktionen etc. wusste.</p>
<p>Doch noch was zu den const-Funktionen: Ich verstehe schon, dass in diesem Zusammenhang (wenn Enemy konstant ist) auch die Memberfunktionen einen konstanten Rückgabewert haben müssen. Jedoch gebe ich bei meinen Funktionen mit Rückgabetyp sowieso immer einen Wert zurück, spricht da etwas dagegen, alle Funktionen à la GetAnything() konstant zu deklarieren? Wäre das nur bei der Rückgabe von Zeigern oder Referenzen von Bedeutung? Ich verstehe nicht ganz, welchen tatsächlichen Unterschied es macht ob ich jetzt <em>short GetType()</em> oder <em>short GetType() const</em> schreibe (ich meine allgemein, nicht nur wenn die Klasse selber konstant übergeben wird)... solange ich in der Funktion nur <em>return Type;</em> aufgeschrieben habe, kann ja eh nichts verändert werden, oder?</p>
<p>Noch was: ist <em>const short GetType() const</em> das gleiche wie <em>short GetType() const</em>?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486367</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486367</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 10:50:13 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 11:14:42 GMT]]></title><description><![CDATA[<p>Wenn eine Memberfunktion const deklariert ist bedeutet das nicht, dass der Rückgabewert const ist, sondern, das die Funktion aufgerufen wird, wenn die dahinterliegende Instanz const ist. Es darf also in einer solchen Funktion kein Member der Klasse verändert werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486379</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486379</guid><dc:creator><![CDATA[Braunstein]]></dc:creator><pubDate>Fri, 04 Apr 2008 11:14:42 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 11:29:27 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Vielen Dank für die zahlreichen Antworten! Ich hätte nicht gedacht, dass wegen eines einzigen Zeigers ein solcher Mehraufwand erforderlich ist ;)...</p>
</blockquote>
<p>Da merkst Du mal, welch Vorteil es ist, &quot;Objekte&quot;/Stackvariablen zu haben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /><br />
Das Problem macht nämlich nicht der Zeiger, sondern die (Möglichkeit der) dynamische(n) Verwaltung.<br />
Sie hat auch Vorteile, aber die kosten eben auch etwas (wie z.B. hier).</p>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486383</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486383</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Fri, 04 Apr 2008 11:29:27 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 11:51:03 GMT]]></title><description><![CDATA[<p>@ Simon2<br />
Mit der Zeit werde ich kaum darum herum kommen, deshalb ist es nicht mal so schlecht... Ich frag mich nur ein bisschen, da ich bis jetzt schon ganze 2D-Spiele geschrieben habe, ohne jemals etwas von Kopierkonstruktor etc. gehört zu haben <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>@ Braunstein<br />
Danke für die Erläuterung, das hab ich nicht ganz richtig begriffen. Ich versteh folgenden Unterschied aber immer noch nicht, hat es hier etwas mit dem Rückgabetyp zu tun (da ja das Schlüsselwort const vorne steht):</p>
<pre><code class="language-cpp">const short GetType() const;
short GetType() const;
</code></pre>
<p>Zudem ist mir immer noch nicht klar, was dafür spricht, Memberfunktionen wie GetType(), die nur einen Wert zurückgeben, als nicht-konstant zu deklarieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486398</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486398</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 11:51:03 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 11:59:26 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Zudem ist mir immer noch nicht klar, was dafür spricht, Memberfunktionen wie GetType(), die nur einen Wert zurückgeben, als nicht-konstant zu deklarieren.</p>
</blockquote>
<p>Gar nichts. Diese Funktionen sollten auch immer const sein. Es gibt auch da sicher Ausnahmefälle (lazy evaluation?).</p>
<pre><code class="language-cpp">const short GetType() const;
</code></pre>
<p>Konstante Memberfunktion die ein const short zurückgibt. Das wäre hier recht unsinnig, da der Rückgabewert eh kopiert wird.</p>
<pre><code class="language-cpp">short GetType() const;
</code></pre>
<p>Konstante Memberfunktion die ein short (nicht konstant) zurückgibt.<br />
In diesem Fall sind aber beide Funktionen identisch. Das wären ja auch keine möglichen Überladungen, da der Rückgabetyp ja nicht zur Funktionssignatur gehört.<br />
Sinn machen konstante Rückgabewerte ja eher bei Referenzen oder Zeigern.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486402</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486402</guid><dc:creator><![CDATA[Braunstein]]></dc:creator><pubDate>Fri, 04 Apr 2008 11:59:26 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 12:02:05 GMT]]></title><description><![CDATA[<p>Okay, vielen Dank für die schnelle Antwort!<br />
Dann mache ich eben alle GetBlabla-Funktionen konstant <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486405</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486405</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 12:02:05 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 12:53:59 GMT]]></title><description><![CDATA[<p>Braunstein schrieb:</p>
<blockquote>
<pre><code class="language-cpp">const short GetType() const;
</code></pre>
<p>Konstante Memberfunktion die ein const short zurückgibt. Das wäre hier recht unsinnig, da der Rückgabewert eh kopiert wird.</p>
<pre><code class="language-cpp">short GetType() const;
</code></pre>
<p>Konstante Memberfunktion die ein short (nicht konstant) zurückgibt.<br />
In diesem Fall sind aber beide Funktionen identisch.</p>
</blockquote>
<p>Treffsicher daneben.<br />
Beide Deklarationen deklarieren ein und dieselbe Funktion. (Top-level) cv-Qualifizierer des Rückgabewertes sind nicht Teil des Funktionsstyps, wenn der Rückgabewert skalar ist. Das wird klar, wenn man sich überlegt, dass das Ergebnis eines entsprechenden Funktionsaufrufes ein rvalue ist, und skalare rvalues sind niemals cv-qualifiziert (weil es keine Objekte sondern nur der Wert an sich - das Bitmuster, wenn man so will - sind).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486437</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486437</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 04 Apr 2008 12:53:59 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 15:15:24 GMT]]></title><description><![CDATA[<p>Okay, das verwirrt mich jetzt ein bisschen...<br />
Versteh ich dich richtig, dass nur ein Wert (R-Value) zurückgegeben wird, und es keine Rolle spielt, ob der konstant ist oder nicht, weil er sowieso nicht verändert wird? (Sorry kenn mich eben nicht so aus mit deinen Fachausdrücken :D).</p>
<p>Heisst das in diesem Fall, man kann das erste <em>const</em> von <em>const short GetType() const</em> immer weglassen? Wieso ermöglicht es dann die C++-Syntax, es vorher zu schreiben, wenn es so oder so überflüssig ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486562</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486562</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 15:15:24 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 16:19:41 GMT]]></title><description><![CDATA[<blockquote>
<p>Heisst das in diesem Fall, man kann das erste <em>const</em> von <em>const short GetType() const</em> immer weglassen?</p>
</blockquote>
<p>ja, weil short ein <a href="http://www.c-plusplus.net/forum/viewtopic-var-t-is-194356.html" rel="nofollow">skalarer</a> Typ ist. Das besondere an skalaren Typen ist, dass sie eine einzelne unteilbare Einheit bilden: man kann hier also sehr schön trennen zwischen dem Speicher (=Objekt) eines solchen Typs und dem Zustand dieses Speichers. Ein Ausdruck skalaren Typs (bei Klassen/Arrays/Funktionen/Referenzen wird es komplizierter) kann nun (ganz allgemein) entweder auf ein Objekt (=Speicherstelle) verweisen oder nur den Wert (=Zustand) an sich bezeichnen. Ersteres stellt einen lvalue-Ausdruck dar, letzteres ein rvalue. Nun ist aber klar, dass die Eigenschaft, konstant oder volatile zu sein, nur bestimmtem Speicher zukommen kann. Bezogen auf einen bestimmten Zustand (man denke zum Beispiel auch ein ein einfaches Literal wie 1 - dem entspricht ein bestimmtes Bitmuster vom Typ int) sind diese Begriffe sinnlos. Die Konsequenz ist, dass solche (skalaren) Rvalues <em>niemals</em> cv-qualifiziert sind. Immer dann, wenn einer Konvertierung eines Lvalues in ein Rvalue erfolgt (das entspricht im Allgemeinen dem Lesen einer Variablen, also der Bestimmung des <em>Zustands</em> einer bestimmten Speicherstelle), gehen evtl. vorhandene Qualifikationen des Objektes verloren, nach dem Lesevorgang haben diese keine Bedeutung mehr.<br />
Der Rest ergibt sich damit im Grunde von selbst. Der Compiler unterscheidet nicht zwischen beiden Deklarationen, weil er es gar nicht kann.</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Wieso ermöglicht es dann die C++-Syntax, es vorher zu schreiben, wenn es so oder so überflüssig ist?</p>
</blockquote>
<p>Das ist keine syntaktische Frage. Der Rückgabetyp könnte ja auch durch ein typedef konstant erscheinen (der tatsächlich deklarierte Rückgabetyp ist auch dann wiederum unqualifiziert), dann sieht man das der Deklaration gar nicht unmittelbar an. Zudem, was wichtiger ist, ist nicht jeder Ausdruck skalar, und für bestimmte Typen (primär Klassen) existieren cv-qualifizierte Rvalues.</p>
<p>Bleibt noch anzumerken, dass es - meiner Meinung nach - fast nie sinnvoll ist, den Rückgabetyp konstant zu machen (wie oben geklärt, spielt es sowieso nur bei Klassen eine Rolle). Die Gründe dafür sind nicht sonderlich kompliziert. Hauptsächlich geht es um Kapselung - eine Funktion sollte so wenig wie möglich vom Aufrufer verlangen (=möglichst allgemeiner Parameter) und möglichst viel versprechen (=Garantien über die Rückgabe liefern, mit einem veränderbaren Objekt kann man <em>mehr</em> machen, als mit einem konstanten), aber das sprengt ein bisschen den Rahmen dieser Diskussion.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486597</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486597</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 04 Apr 2008 16:19:41 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 16:19:18 GMT]]></title><description><![CDATA[<p>Okay, vielen Dank für diese umfassende Antwort!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486604</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486604</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Fri, 04 Apr 2008 16:19:18 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 16:56:59 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Bleibt noch anzumerken, dass es - meiner Meinung nach - fast nie sinnvoll ist, den Rückgabetyp konstant zu machen (wie oben geklärt, spielt es sowieso nur bei Klassen eine Rolle). Die Gründe dafür sind nicht sonderlich kompliziert. Hauptsächlich geht es um Kapselung - eine Funktion sollte so wenig wie möglich vom Aufrufer verlangen (=möglichst allgemeiner Parameter) und möglichst viel versprechen (=Garantien über die Rückgabe liefern, mit einem veränderbaren Objekt kann man <em>mehr</em> machen, als mit einem konstanten), aber das sprengt ein bisschen den Rahmen dieser Diskussion.</p>
</blockquote>
<p>Und deshalb ist es gut<br />
(a+b)=c;<br />
zu erlauben?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486631</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486631</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Fri, 04 Apr 2008 16:56:59 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 19:55:06 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>Bleibt noch anzumerken, dass es - meiner Meinung nach - fast nie sinnvoll ist, den Rückgabetyp konstant zu machen (wie oben geklärt, spielt es sowieso nur bei Klassen eine Rolle). Die Gründe dafür sind nicht sonderlich kompliziert. Hauptsächlich geht es um Kapselung - eine Funktion sollte so wenig wie möglich vom Aufrufer verlangen (=möglichst allgemeiner Parameter) und möglichst viel versprechen (=Garantien über die Rückgabe liefern, mit einem veränderbaren Objekt kann man <em>mehr</em> machen, als mit einem konstanten), aber das sprengt ein bisschen den Rahmen dieser Diskussion.</p>
</blockquote>
<p>Und deshalb ist es gut<br />
(a+b)=c;<br />
zu erlauben?</p>
</blockquote>
<p>Ich sehe daran nicht so viel Schlimmes. Die geerbte C-Syntax erlaubt ohnehin eine Menge Mist. Schreibt man das mit Klammern, ist sowieso Machiavelli am Werk - oder jemand mit einem Klammerfetisch (etwas, das ich nicht besonders mag, es kann helfen Präzedenz zu klären, aber häufig wird ein Ausdruck auch unverständlicher, wenn man nur nach am Klammerabzählen ist). Gefährlich könnte es werden, wenn wir eigentlich einen Vergleich schreiben wollten. Das passiert für gewöhnlich in if,while-statements; und hier sind moderne Compiler in der Regel sehr mitteilungsfreudig - es ist also imo kein praktisches Problem, wenn man die Warnungen des Compilers gelegentlich liest. Es bliebe der Fall, wenn der eigentlich gewollte Vergleich nur ein Subausdruck ist. Solche Fälle sind eher selten und per se schwerer zu verstehen, hier ist in jedem Falle erhöhte Aufmerksamkeit gefordert, oder man verzichtet darauf - auch ein C-Erbe i.w.S.</p>
<p>Wäre es gut, es nicht zu erlauben? Sicherlich, aber das Mittel ist ungeeignet. Der Defekt, wenn man das so bezeichnen will, liegt ja beim Zuweisungsoperator, nicht bei der Addition.<br />
Und dann wäre da noch<br />
c=a+b<br />
Ist obiges Problem wirklich so gravierend, dass wir mit Freude auf Move-Kopiererei verzichten würden? Da habe ich große Zweifel.<br />
Persönlich finde ich, dass das a+b=c Problem unnötig aufgebauscht wurde. Hier wird eine relativ isolierte Problematik zum Anlass genommen, potentiell das Design nahezu jeder Funktion zu beeinflussen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486711</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486711</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 04 Apr 2008 19:55:06 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 20:53:38 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Ist obiges Problem wirklich so gravierend, dass wir mit Freude auf Move-Kopiererei verzichten würden?</p>
</blockquote>
<p>Warum sollte ein move nicht funktionieren? Wenn ich mir zB Mojo ansehe - dann wuerde (a+b)=c wohl sowieso nicht klappen.</p>
<p>oder uebersehe ich etwas? welchen nachteil hat es, ein (a+b)=c zu verbieten und sich so an die builtin semantic zu halten. denn zuweisung an temopraere objekte ist immer boese. es sei denn jemand hat eine situation wo das sinn machen kann...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486734</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486734</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Fri, 04 Apr 2008 20:53:38 GMT</pubDate></item><item><title><![CDATA[Reply to Zugriffsverweigerung bei Destruktor on Fri, 04 Apr 2008 21:55:36 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p>Ist obiges Problem wirklich so gravierend, dass wir mit Freude auf Move-Kopiererei verzichten würden?</p>
</blockquote>
<p>Warum sollte ein move nicht funktionieren? Wenn ich mir zB Mojo ansehe - dann wuerde (a+b)=c wohl sowieso nicht klappen.</p>
<p>oder uebersehe ich etwas? welchen nachteil hat es, ein (a+b)=c zu verbieten und sich so an die builtin semantic zu halten. denn zuweisung an temopraere objekte ist immer boese. es sei denn jemand hat eine situation wo das sinn machen kann...</p>
</blockquote>
<p>Ich glaube wir reden aneinander vorbei. Ich habe nichts dagegen a+b=c zu verbieten, sofern die Methode nicht darin besteht, Funktionsergebnisse konstant zu machen. Die Frage ist doch gar nicht, ob es gut oder schlecht ist so etwas zu verbieten, sondern ob es den Preis wert ist, indem automatisch andere <em>sinnvolle</em> Konstrukte gleichzeitig unmöglich werden.<br />
Ob Zuweisung an temporäre Objekte wirklich so furchtbar böse ist, kann auch bezweifelt werden oder ist eine Frage, wie das zu verstehen sein soll: im Allgemeinen ist es nur sinnlos, als böse würde ich etwas erst bezeichnen, wenn es versehentlich etwas anderes als das Offensichtliche tut oder leicht unbemerkt als versehentlicher Schreibfehler entsteht. Zu Ersteres fällt mir nichts ein, für Letzteres gibt es meiner Erfahrung nach adäquate Compilerunterstützung.</p>
<p>Wenn a+b konstant ist (und nur darum geht es), kann c=a+b keine move-Unterstützung anbieten (unabhängig vom System, ob nun mit Mojo, Abrahams' Methode oder rvalue-Referenzen) ohne undefiniertes Verhalten zu provozieren. Move-Unterstützung ist nur ein Fall, es gibt viele Fälle in denen wir ein temporäres Objekt zwar nicht zuweisen aber doch verändern wollen. In Abwesenheit von Move-Semantik (und Expression Templates etc), könnte zum Beispiel so etwas sinnvoll sein:<br />
a=((a*b)+=c);<br />
oder<br />
foo((a+b).trim()) (a,b: irgenwelche strings)<br />
keines dieser Beispiele ist für sich genommen besonders wichtig und man könnte ohne Weiteres darauf verzichten (in der Regel machbar, wenn wir eine zusätzliche Variable an Stelle des temporären Objektes einführen und auf Copy-Elision vertrauen), in ihrer Gesamtheit erscheint mir das Verbot dieser ganzen Klasse von Konstrukten übertrieben nur um ein relativ obskures Problem mit der Zuweisung zu lösen, mit dem ich noch nie zu tun hatte. Abgesehen von diesen Beispielen gefällt es mir schon systematisch nicht, weil an der falschen Stelle angesetzt wird und auch nicht aus sich selbst heraus begründet werden kann, mit der Aufgabe der Funktion, die betroffen ist, hat das Ganze schließlich nichts zu tun. Die Argumentation mit der &quot;built-in-Semantic&quot; ist da ein bisschen fragwürdig. Wenn wir dahin wollen, müssen wir dem Ergebnis solcher Operatoren den Objektcharakter wegnehmen (offensichtlich unmöglich), mit const kommen wir nicht dahin.</p>
<p>Ich halte es nicht für richtig, dem Nutzer Konstrukte, die wir ggf. mißbilligen, zu verbieten, wenn eine Empfehlung in dieser Hinsicht genügen müsste. Zumindest erscheint mir das Problem einfach nicht schwerwiegend genug um einen dermaßen massiven Eingriff in die Deklaration <em>jeder einzelnen</em> Funktion, die Klassenobjekte zurückgibt, zu rechtfertigen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1486755</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1486755</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 04 Apr 2008 21:55:36 GMT</pubDate></item></channel></rss>