<?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[Speicher freigeben: Aufrufer oder Klasse?]]></title><description><![CDATA[<p>Wenn eine Klasse einen Zeiger besitzt, und diesem durch den Aufrufer die Adresse eines Speicherbereichs auf dem Heap zugewiesen wird: wer sollte am besten die Verantwortung für das Löschen übernehmen? Der Aufrufer oder die Klasse, die den Zeiger hat?</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">class B
{
    private:
        int _x;
    public:
        B(int x) :_x(x) {} 
}

class A
{
    private:
        B* einB;
    public:
        A(B* b) :einB(b) {}
}
</code></pre>
<p>so?</p>
<pre><code class="language-cpp">int main()
{
    B* b = new B(7);
    A a(b);
    delete b;
}
</code></pre>
<p>oder so:</p>
<pre><code class="language-cpp">int main()
{
    B* b = new B(7);
    A a(b);
}
</code></pre>
<p>und die Klasse A würde in diesem Fall einen Destruktor haben:</p>
<pre><code class="language-cpp">~A() 
{ 
    delete einB; 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/157016/speicher-freigeben-aufrufer-oder-klasse</link><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 01:32:56 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/157016.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 22 Aug 2006 14:31:56 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 14:31:56 GMT]]></title><description><![CDATA[<p>Wenn eine Klasse einen Zeiger besitzt, und diesem durch den Aufrufer die Adresse eines Speicherbereichs auf dem Heap zugewiesen wird: wer sollte am besten die Verantwortung für das Löschen übernehmen? Der Aufrufer oder die Klasse, die den Zeiger hat?</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">class B
{
    private:
        int _x;
    public:
        B(int x) :_x(x) {} 
}

class A
{
    private:
        B* einB;
    public:
        A(B* b) :einB(b) {}
}
</code></pre>
<p>so?</p>
<pre><code class="language-cpp">int main()
{
    B* b = new B(7);
    A a(b);
    delete b;
}
</code></pre>
<p>oder so:</p>
<pre><code class="language-cpp">int main()
{
    B* b = new B(7);
    A a(b);
}
</code></pre>
<p>und die Klasse A würde in diesem Fall einen Destruktor haben:</p>
<pre><code class="language-cpp">~A() 
{ 
    delete einB; 
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1122195</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122195</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Tue, 22 Aug 2006 14:31:56 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 14:37:29 GMT]]></title><description><![CDATA[<p>kommt drauf an.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122201</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122201</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 22 Aug 2006 14:37:29 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 14:38:26 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>kommt drauf an.</p>
</blockquote>
<p>auf was?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122202</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122202</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Tue, 22 Aug 2006 14:38:26 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 14:45:38 GMT]]></title><description><![CDATA[<p>Wie du dich entscheidest. Aber bitte immer deutlich dokumentieren. Wenn deine Klasse die verantwortung übernehmen soll, solltest du einen auto_ptr verwenden, das müsste explizit genug sein.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122211</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122211</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Tue, 22 Aug 2006 14:45:38 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 14:48:56 GMT]]></title><description><![CDATA[<p>Im allgemeinen sollte wohl derjenige, der den Speicher beschafft, ihn auch wieder freigeben. Ausnahmen sind natürlich Klassen, die sich explizit um dieses Speichermanagement kümmern, indem sie einen Zeiger kapseln (wie z.B. std::auto_ptr).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122217</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122217</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Tue, 22 Aug 2006 14:48:56 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 15:11:31 GMT]]></title><description><![CDATA[<p>Konrad Rudolph schrieb:</p>
<blockquote>
<p>Im allgemeinen sollte wohl derjenige, der den Speicher beschafft, ihn auch wieder freigeben. Ausnahmen sind natürlich Klassen, die sich explizit um dieses Speichermanagement kümmern, indem sie einen Zeiger kapseln (wie z.B. std::auto_ptr).</p>
</blockquote>
<p>Genau das ist (fast immer) so! Ich habe bemerkt, dass die &quot;Übergabe von alleinigen Besitzerrechten&quot; (std::auto_ptr) eigentlich nur selten gebraucht wird. Ist auf jeden bei uns so, kommt sicher auch auf den Programmierstil an.<br />
Aber ich glaube nicht, dass in diesem Beispiel der Speicher nur noch A gehören soll, sonst könnte A das Objekt ja selber instanzieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122229</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122229</guid><dc:creator><![CDATA[Thomas ** 0]]></dc:creator><pubDate>Tue, 22 Aug 2006 15:11:31 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 15:48:33 GMT]]></title><description><![CDATA[<p>Soweit einleuchtend.</p>
<p>Stellt euch nun ein vector mit Objeketen der obigen Klasse A (zur Erinnerung: enthält Zeiger auf <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--smiling_face_with_sunglasses"
      title="B)"
      alt="😎"
    /> vor:</p>
<pre><code class="language-cpp">class X
{
    private:
        std::vector&lt;A&gt; viele_A;
    public:
        void add_A(const A&amp; a)
        {
            viele_A.push_back(a);
        } 
}
</code></pre>
<pre><code class="language-cpp">int main()
{
    B* b = new B(17);
    A a(b);
    X x;
    x.push_back(a);
    x.push_back(a);
    x.push_back(a);
    //...
    delete b; //oder lieber die Klasse A das erledigen lassen??
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1122250</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122250</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Tue, 22 Aug 2006 15:48:33 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 15:55:17 GMT]]></title><description><![CDATA[<p>wie soll a das objekt b löschen wenn mehrere As sich ein B teilen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122252</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122252</guid><dc:creator><![CDATA[lolz]]></dc:creator><pubDate>Tue, 22 Aug 2006 15:55:17 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 16:04:59 GMT]]></title><description><![CDATA[<p>lolz schrieb:</p>
<blockquote>
<p>wie soll a das objekt b löschen wenn mehrere As sich ein B teilen?</p>
</blockquote>
<p>Das ginge schon, z.B. mit einem Referentzzähler in A. Aber ich sähe hier den Sinn nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122258</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122258</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Tue, 22 Aug 2006 16:04:59 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 16:08:51 GMT]]></title><description><![CDATA[<p>So wie der Code jetzt ist ist er auf jeden Fall böse. Woher sollen die As wissen, dass ihr B* nicht mehr gültig ist? Du müsstest hier auf jeden Fall irgendwas mit Referenzzählung machen, am Besten automatisiert wie in <a href="http://www.boost.org/libs/smart_ptr" rel="nofollow">Boost.SmartPointer</a>.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122259</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122259</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Tue, 22 Aug 2006 16:08:51 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 17:28:45 GMT]]></title><description><![CDATA[<p>Konrad Rudolph schrieb:</p>
<blockquote>
<p>lolz schrieb:</p>
<blockquote>
<p>wie soll a das objekt b löschen wenn mehrere As sich ein B teilen?</p>
</blockquote>
<p>Das ginge schon, z.B. mit einem Referentzzähler in A. Aber ich sähe hier den Sinn nicht.</p>
</blockquote>
<p>dann gibt a aber eine resource wieder frei und löscht sie nicht (ok, wenn die klasse nicht wohlgeformt ist, dann geht da sschon)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122326</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122326</guid><dc:creator><![CDATA[lolz]]></dc:creator><pubDate>Tue, 22 Aug 2006 17:28:45 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 17:48:40 GMT]]></title><description><![CDATA[<p>.filmor schrieb:</p>
<blockquote>
<p>Du müsstest hier auf jeden Fall irgendwas mit Referenzzählung machen, am Besten automatisiert wie in<br />
<a href="http://www.boost.org/libs/smart_ptr" rel="nofollow">Boost.SmartPointer</a>.</p>
</blockquote>
<p>Ich bin mal grob drübergeflogen.</p>
<p>Bisher kannte ich nur auto_ptr.</p>
<p>Wäre shared_ptr hier das richtige für die B-Objekte?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122340</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122340</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Tue, 22 Aug 2006 17:48:40 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 17:54:09 GMT]]></title><description><![CDATA[<p>Ja. Zumindest mit den Informationen, die du gegeben hast.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122344</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Tue, 22 Aug 2006 17:54:09 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Tue, 22 Aug 2006 18:08:19 GMT]]></title><description><![CDATA[<p>.filmor schrieb:</p>
<blockquote>
<p>Zumindest mit den Informationen, die du gegeben hast.</p>
</blockquote>
<p>In meinem &quot;richtigen&quot; Programm gibt es &quot;nur&quot; den Unterschied, dass die Objekte der Klasse A selbst als Zeiger im Vector gespeichert werden (da es recht große Objekte sind):</p>
<pre><code class="language-cpp">class X
{
    private:
        std::vector&lt;A*&gt; viele_APointer;
</code></pre>
<p>}</p>
<p>Diese Zeiger werden im Destruktor der Klasse X gelöscht:</p>
<pre><code class="language-cpp">X::~X()
{
    for (int i = 0; i &lt; viele_APointer.size(); ++i)
        delete viele_APointer[i];
}
</code></pre>
<p>Ändert das was an der Situation?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122347</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122347</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Tue, 22 Aug 2006 18:08:19 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Wed, 23 Aug 2006 06:45:44 GMT]]></title><description><![CDATA[<p>Hmm, ich blick da im Moment nicht so richtig durch (kann auch an der Frühe liegen ;)).<br />
So wie es jetzt aussieht ist doch die Zuständigkeit klar geregelt, die liegt nämlich bei dem X-Objekt?!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122531</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122531</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Wed, 23 Aug 2006 06:45:44 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Wed, 23 Aug 2006 07:33:11 GMT]]></title><description><![CDATA[<p>.filmor schrieb:</p>
<blockquote>
<p>Hmm, ich blick da im Moment nicht so richtig durch (kann auch an der Frühe liegen ;)).<br />
So wie es jetzt aussieht ist doch die Zuständigkeit klar geregelt, die liegt nämlich bei dem X-Objekt?!</p>
</blockquote>
<p>Das ist noch nicht zu sehen. Die Frage ist: Wer macht das &quot;new&quot; ?<br />
Der Aufrufer ?</p>
<pre><code class="language-cpp">void X::add(A* a) { viele_A.push_back(a); }
int main(int argc, char* argv[]) {
    A* a = new A();
    X x;
    x.add(a);
    delete a; // BÖÖÖÖÖSE
};
</code></pre>
<p>... oder das X</p>
<pre><code class="language-cpp">void X::add(A&amp; a) { 
    A* myA = new A(a); // kostet eine CopyKonstruktion
    viele_A.push_back(myA);
}

int main(int argc, char* argv[]) {
    A* pa = new A();
    A a;
    X x;
    x.add(*pa);
    delete pa; // macht nix
    x.add(a);
};
</code></pre>
<p>Alternativ kann man natürlich die Zuständigkeit komplett aus X herausverlegen:</p>
<pre><code class="language-cpp">class X
{
    public:
        X::~X() {}
        A* getA(int i) { return viele_APointer.at(i); }
        int getAcount() { return viele_APointer.size(); }
};
// Benutzer muss eine &quot;delete-Schleife&quot; implementieren
</code></pre>
<p>Aber das sieht nach einem selbstgestrickten &quot;Container-Wrapper&quot; aus, bei dem ich sehr vorsichtig wäre; da steckt der Teufel oft im Detail.</p>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1122553</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1122553</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Wed, 23 Aug 2006 07:33:11 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Thu, 24 Aug 2006 09:35:12 GMT]]></title><description><![CDATA[<p>Weil das stückchenweise Code posten für etwas Verwirrung gesorgt hat, hier noch mal alles auf einen Blick, wie der aktuelle Stand der Dinge 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="😉"
    /></p>
<pre><code class="language-cpp">class B
{
//unwichtig (enthält keine Zeiger)
}

class A
{
    private:
        B* _b;
        int _y;
    public:
        A(B* b, int y) :_b(b), :_y(y) {}
}

class X
{
    private:
        std::vector&lt;A*&gt; viele_A;
    public:
        void add_A(A* a)
        {
            viele_A.push_back(a);
        }
        ~X()
        {
            for (int i = 0; i &lt; viele_A.size(); ++i)
            {
                delete[i];
            }
        }
};
</code></pre>
<pre><code class="language-cpp">int main()
{
    B* b = new B;
    X x;
    x.add_A(new A(b, 0);
    x.add_A(new A(b, 1);
    x.add_A(new A(b, 2);
    delete b;
}
</code></pre>
<p>Also für mich stellt sich das wie folgt dar:</p>
<ol>
<li>Es wird _einmal_ ein neues B auf dem Heap erzeugt.</li>
<li>In den Vector viele_A werden Speicheradressen auf Objekte der Klasse A auf dem Heap gespeichert.<br />
-&gt; diese Objekte werden auch schön wieder im Destruktor der Klasse X freigegeben.</li>
<li>Jedem Objekt der Klasse A wird als Parameter neben dem int-Wert noch die Adresse auf das Objekt der Klasse B auf dem Heap mitgegeben.<br />
-&gt; um die Freigabe dieses Objekts der Klasse B kümmert sich der Aufrufer mit delete b;</li>
</ol>
<p>So, und jetzt seid ihr dran mir zu erzählen, warum dieser Code böse ist / wie man es anders machen sollte / ob smart pointer wie der shared_ptr nötigt sind. <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/1123497</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1123497</guid><dc:creator><![CDATA[sly]]></dc:creator><pubDate>Thu, 24 Aug 2006 09:35:12 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Thu, 24 Aug 2006 09:48:00 GMT]]></title><description><![CDATA[<p>Du musst dir nur über die Zuständigkeiten Gedanken machen:<br />
A -&gt; wird von X verwaltet. (Falls A polymorph ist solltest du dir Boost.PointerContainer anschauen)<br />
X -&gt; liegt auf dem Stack<br />
B -&gt; nicht ganz eindeutig. Falls du SharedPointer verwendest, musst du den echten Zeiger direkt nach dem Einfügen unschädlich machen:</p>
<pre><code class="language-cpp">int main()
{
    X x;
    {
        B* b = new B;
        x.add_A(new A(b, 0);
        x.add_A(new A(b, 1);
        x.add_A(new A(b, 2);
    }
}
</code></pre>
<p>Das Beispiel ist aber meiner Meinung nach zu abstrakt, um eine Entscheidung für oder gegen SharedPointer zu fällen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1123518</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1123518</guid><dc:creator><![CDATA[.filmor]]></dc:creator><pubDate>Thu, 24 Aug 2006 09:48:00 GMT</pubDate></item><item><title><![CDATA[Reply to Speicher freigeben: Aufrufer oder Klasse? on Thu, 24 Aug 2006 12:24:44 GMT]]></title><description><![CDATA[<p>Hi sly,</p>
<p>ich würde</p>
<ul>
<li>&quot;die As&quot; von X erzeugen lassen und</li>
<li>&quot;den As&quot; nur ein B&amp; übergeben.</li>
</ul>
<p>Dann ist die Zuständigkeit klar.</p>
<p>Wenn Dein B tatsächlich ein &quot;singleton&quot; ist, könntest Du es in ein solches Pattern einsetzen .... wenn das aber aufwendiger als notwendig ist, kann man eine Referenz in den X-Ctor aufnehmen....</p>
<p>...und ganz sauber wäre es dann, wenn Du noch auf const-correctness achtest.<br />
(Ich tue jetzt mal so, als ob A und X keine non-const-Methoden von B aufrufen)</p>
<pre><code class="language-cpp">class B
{
//unwichtig (enthält keine Zeiger)
}

class A
{
    private:
        const B&amp; _b;
        int _y;
    public:
        A(const B&amp; b, int y) :_b(b), :_y(y) {}
}

class X
{
    private:
        const B&amp; _b;
        std::vector&lt;A*&gt; viele_A;
        // Kopieren unterbinden
        X(const X&amp;);
        const X&amp; operator=(const X&amp;);
    public:
        X(const B&amp; b) : _b(b) {}
        void add_A(int i) {
            viele_A.push_back(new A(b, i));
        }
        ~X() {
            for (int i = 0; i &lt; viele_A.size(); ++i) {
                delete[i];
            }
        }
};
</code></pre>
<pre><code class="language-cpp">int main()
{
    B* b = new B;
    X x(*b);
    x.add_A(0);
    x.add_A(1);
    x.add_A(2);
    delete b;
}
</code></pre>
<p>Gruß,</p>
<p>Simon2.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1123718</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1123718</guid><dc:creator><![CDATA[Simon2]]></dc:creator><pubDate>Thu, 24 Aug 2006 12:24:44 GMT</pubDate></item></channel></rss>