<?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[Reihenfolge von Destruktor-Aufrufen]]></title><description><![CDATA[<p>Ein Hallo in die Runde!</p>
<p>Beim Experimentieren mit libsdl (hier: Das Schreiben eines Wrappers für die Struktur SDL_Surface) habe ich aus einem mir unerfindlichen Grund immer wieder Segmentation-Faults erhalten. Um das Problem zumindest logisch nachvollziehen zu können, habe ich das Problem mit einer &quot;Foo&quot;-Klasse abstrahiert und habe festgestellt, dass es mit der Reihenfolge zusammen hängt, wie der Destruktor der Klasse &quot;Foo&quot; aufgerufen wird.</p>
<p>OS: Windows XP-Pro, DevC++</p>
<p>Hier die &quot;Foo&quot;-Klasse nebst Verwendung (vollständige Quelldatei):</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class Foo
{
private:
    int value;

public:
    Foo()
        : value(0)
        {
            cout    &lt;&lt; &quot;Foo: default-ctor&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object created at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

    Foo(int value)
        : value(value)
        {
            cout    &lt;&lt; &quot;Foo: ctor (int=&quot; &lt;&lt; this-&gt;value &lt;&lt; &quot;)&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object created at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

    virtual ~Foo()
        {
            cout    &lt;&lt; &quot;Foo: dtor (value was &quot; &lt;&lt; value &lt;&lt; &quot;)&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object destroyed at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

};

int main(int argc, char** args)
    {
        {
            Foo bar = 1;
            bar = 2;
            bar = 3;
        }
        return 0;
    }
</code></pre>
<p>Das obenstehende Programm produzierte folgende ausgabe auf der Konsole:</p>
<pre><code>Foo: ctor (int=1)
    object created at 0x22ff50

Foo: ctor (int=2)
    object created at 0x22ff40

Foo: dtor (value was 2)
    object destroyed at 0x22ff40

Foo: ctor (int=3)
    object created at 0x22ff40

Foo: dtor (value was 3)
    object destroyed at 0x22ff40

Foo: dtor (value was 3)
    object destroyed at 0x22ff50
</code></pre>
<p>Die Zeilen 4 bis 14 kann ich nachvollziehen, das ist auch das Verhalten, was ich erwartet habe. Was mich stört ist, dass das Objekt, welches im ersten Konstruktoraufruf (Quelltextzeile 38, Ausgabezeile 1+2) erst zerstört wird, wenn der Block verlassen wird (Quelltextzeile 41) und nicht, <em>wie ich es erwartet hätte</em>, beim zweiten Konstruktoraufruf. Vielmehr wird hier ein zusätzliches Objekt angelegt.</p>
<p>Nun meine Frage: Wie ist dieses Verhalten zu erklären?</p>
<p>Um Erleuchtung bittende Grüße aus dem Sauerland</p>
<p>Heiko</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/191114/reihenfolge-von-destruktor-aufrufen</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 21:34:47 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/191114.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 30 Aug 2007 10:50:11 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Reihenfolge von Destruktor-Aufrufen on Thu, 30 Aug 2007 10:50:11 GMT]]></title><description><![CDATA[<p>Ein Hallo in die Runde!</p>
<p>Beim Experimentieren mit libsdl (hier: Das Schreiben eines Wrappers für die Struktur SDL_Surface) habe ich aus einem mir unerfindlichen Grund immer wieder Segmentation-Faults erhalten. Um das Problem zumindest logisch nachvollziehen zu können, habe ich das Problem mit einer &quot;Foo&quot;-Klasse abstrahiert und habe festgestellt, dass es mit der Reihenfolge zusammen hängt, wie der Destruktor der Klasse &quot;Foo&quot; aufgerufen wird.</p>
<p>OS: Windows XP-Pro, DevC++</p>
<p>Hier die &quot;Foo&quot;-Klasse nebst Verwendung (vollständige Quelldatei):</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
using namespace std;

class Foo
{
private:
    int value;

public:
    Foo()
        : value(0)
        {
            cout    &lt;&lt; &quot;Foo: default-ctor&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object created at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

    Foo(int value)
        : value(value)
        {
            cout    &lt;&lt; &quot;Foo: ctor (int=&quot; &lt;&lt; this-&gt;value &lt;&lt; &quot;)&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object created at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

    virtual ~Foo()
        {
            cout    &lt;&lt; &quot;Foo: dtor (value was &quot; &lt;&lt; value &lt;&lt; &quot;)&quot; &lt;&lt; endl
                    &lt;&lt; &quot;    object destroyed at &quot; &lt;&lt; this
                    &lt;&lt; endl &lt;&lt; endl;
        }

};

int main(int argc, char** args)
    {
        {
            Foo bar = 1;
            bar = 2;
            bar = 3;
        }
        return 0;
    }
</code></pre>
<p>Das obenstehende Programm produzierte folgende ausgabe auf der Konsole:</p>
<pre><code>Foo: ctor (int=1)
    object created at 0x22ff50

Foo: ctor (int=2)
    object created at 0x22ff40

Foo: dtor (value was 2)
    object destroyed at 0x22ff40

Foo: ctor (int=3)
    object created at 0x22ff40

Foo: dtor (value was 3)
    object destroyed at 0x22ff40

Foo: dtor (value was 3)
    object destroyed at 0x22ff50
</code></pre>
<p>Die Zeilen 4 bis 14 kann ich nachvollziehen, das ist auch das Verhalten, was ich erwartet habe. Was mich stört ist, dass das Objekt, welches im ersten Konstruktoraufruf (Quelltextzeile 38, Ausgabezeile 1+2) erst zerstört wird, wenn der Block verlassen wird (Quelltextzeile 41) und nicht, <em>wie ich es erwartet hätte</em>, beim zweiten Konstruktoraufruf. Vielmehr wird hier ein zusätzliches Objekt angelegt.</p>
<p>Nun meine Frage: Wie ist dieses Verhalten zu erklären?</p>
<p>Um Erleuchtung bittende Grüße aus dem Sauerland</p>
<p>Heiko</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1355248</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1355248</guid><dc:creator><![CDATA[bwbg]]></dc:creator><pubDate>Thu, 30 Aug 2007 10:50:11 GMT</pubDate></item><item><title><![CDATA[Reply to Reihenfolge von Destruktor-Aufrufen on Thu, 30 Aug 2007 10:57:39 GMT]]></title><description><![CDATA[<p>Hi, an dem Verhalten ist nichts Merkwürdig.</p>
<pre><code class="language-cpp">Foo bar = 1; // C'tor(int) wird aufgerufen
// um 2 in ein Foo reinzustecken muss erst nen Temp Foo-Objekt erzeugt werden
bar = 2;     // bar = Foo(2) C'tor(int), nach Zuweisung temp nicht mehr benötigt -&gt; d'tor
bar = 3;     // dito
}
// bar's Scope wurde verlasssen und wurde deswegen zerstört
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1355255</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1355255</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Thu, 30 Aug 2007 10:57:39 GMT</pubDate></item><item><title><![CDATA[Reply to Reihenfolge von Destruktor-Aufrufen on Thu, 30 Aug 2007 10:57:57 GMT]]></title><description><![CDATA[<p>Zur Einführung: <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>
<pre><code class="language-cpp">Foo bar = 1;
</code></pre>
<p>Copy-Initialization. Entspricht:</p>
<pre><code class="language-cpp">Foo bar = Foo(1);
</code></pre>
<p>Der Compiler hat die Erzeugung der Kopie allerdings weg-optimiert (darf er) und stattdessen eine direct-initialization gemacht, also:</p>
<pre><code class="language-cpp">Foo bar(1);
</code></pre>
<p>Ergebnis sind die Zeilen 1-3 in der Ausgabe:</p>
<blockquote>
<p>Foo: ctor (int=1)<br />
object created at 0x22ff50</p>
</blockquote>
<pre><code class="language-cpp">bar = 2;
</code></pre>
<p>Da du keinen op=(int) definiert hast, wird folgendes ausgeführt:</p>
<pre><code class="language-cpp">bar = Foo(2);
</code></pre>
<p>Es wird also erst ein temporäres Objekt erzeugt:</p>
<blockquote>
<p>Foo: ctor (int=2)<br />
object created at 0x22ff40</p>
</blockquote>
<p>dieses dann über den (automatisch erzeugten) op=(const Foo&amp;) zugewiesen und danach wieder zerstört:</p>
<blockquote>
<p>Foo: dtor (value was 2)<br />
object destroyed at 0x22ff40</p>
</blockquote>
<p>Gleiches Spiel für die nächste Zeile.</p>
<p>Am Ende des Blocks wird dann schließlich bar zerstört, was zur letzten Meldung führt:</p>
<blockquote>
<p>Foo: dtor (value was 3)<br />
object destroyed at 0x22ff50</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/1355256</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1355256</guid><dc:creator><![CDATA[HumeSikkins]]></dc:creator><pubDate>Thu, 30 Aug 2007 10:57:57 GMT</pubDate></item><item><title><![CDATA[Reply to Reihenfolge von Destruktor-Aufrufen on Thu, 30 Aug 2007 10:58:18 GMT]]></title><description><![CDATA[<p>Mit deinem Foo bar = 1 wird der Konstruktor aufgerufen und ein Objekt an 0x22ff50 erstellt. das ist das Objekt was im programm bar heisst.<br />
Bei bar = 2 wird, weil es den operator=(Foo, int) nicht gibt, ein temporaeres Objekt vom Typ Foo erzeugt (implizite Konvertierung von int nach Foo), an 0x22ff40. Dann der durch den Compiler erstellte operator=(Foo, Foo) aufgerufen und das temporaere objekt wieder zerstoert. Dein Objekt bar an 0x22ff50 beinhaltet jetzt den Wert 2.<br />
Das gleiche Spiel nochmal mit implizierter Konvertierung, neuem Objekt (wieder an 0x22ff40, der Platz ist ja wieder frei), operator=(Foo, Foo) und zerstoerung des temporaeren Objekts. Bar beinhaltet jetzt die 3.<br />
Am Ende, bei verlassen des scopes, wird bar ganz normal zerstoert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1355257</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1355257</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Thu, 30 Aug 2007 10:58:18 GMT</pubDate></item><item><title><![CDATA[Reply to Reihenfolge von Destruktor-Aufrufen on Thu, 30 Aug 2007 11:25:21 GMT]]></title><description><![CDATA[<p>Vielen Dank für die ausführlichen Kommentare und weiterführenden Informationen. Alles in allem war es wohl eine Anfängerunachtsamkeit meinerseits.</p>
<p>Von temporären Objekten habe ich schon gehört, aber diese nicht in dem Zusammenhang vermutet. Nun bin ich wieder ein Stückchen schlauer geworden.</p>
<p>Fazit der ganzen Aktion:</p>
<p><em>Explicit is better than implicit</em> - Lasse deinen Compiler weniger Annahmen treffen und du hast weniger Stress.</p>
<p>Erleuchtete Grüße aus dem Sauerland <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>Heiko</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1355277</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1355277</guid><dc:creator><![CDATA[bwbg]]></dc:creator><pubDate>Thu, 30 Aug 2007 11:25:21 GMT</pubDate></item></channel></rss>