<?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 von &#x27;this&#x27; als Smart-Pointer]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe gerade eine Denklblockade bei einer Architektur, die den Smart-Pointer std::tr1::shared_ptr verwendet.</p>
<p>Konkret handelt es sich um einen Interpreter, der aus einer Ausdrucks-Klassen-Hierarchie aufgebaut ist. Die abstrakte Basisklasse besitzt die Methode 'eval'. Diese Methode gibt ein 'shared_ptr&lt;value&gt;' zurück. 'value' selbst erbt von 'expression'. Das heißt, wenn man 'eval' auf einen value ausführt, soll eigentlich eine Referenz auf 'this' zurückgegeben werden. Das ist natürlich aber illegal, weil das Objekt dadurch zu oft zerstört wird. Ich will ungern einen rohen Zeiger zurückgeben, weil es gut sein könnte, dass die 'eval'-Methode für einige Objekte tatsächlich neue Objekte erzeugen muss (das ist sogar der Normalfall). Um diese verwalten zu können, muss ich ja wohl oder übel einen Smart-Pointer zurückgeben.</p>
<p>Kann jemand das Dilemma für mich lösen?</p>
<p>Nochmal zur Verdeutlichung, folgende Beispielklassen (ohne Konstruktoren und sonstiges Beiwerk):</p>
<pre><code class="language-cpp">struct value : public expression { /* … */ };

// Variante mit Smart-Pointer:

struct int_value : public value {
    int m_value;
    shared_ptr&lt;value&gt; eval(context&amp; ctx) {
        shared_ptr&lt;value&gt; ret(this);
        return ret;
    }
};

context ctx;
int_value my_int(42);
shared_ptr&lt;value&gt; result = my_int.eval(ctx);
// BANG: Doppelte Deallokation des aktuellen Objekts.

// Variante ohne Smart-Pointer:

struct int_addition : public binary_expression {
    expression* left;
    expression* right;

    value* eval(context&amp; ctx) {
        value* leftvalue = left.eval(ctx);
        value* rightvalue = right.eval(ctx);
        value* ret = new int_value(ctx.as_int(leftvalue)  + ctx.as_int(rightvalue));
        return ret;
    }
};

context ctx;
int_value x(42);
int_value y(23);
int_addition add(&amp;x, &amp;y);
value* z = add.eval(ctx);
// BANG: Speicherleck.
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/200947/rückgabe-von-this-als-smart-pointer</link><generator>RSS for Node</generator><lastBuildDate>Mon, 05 Oct 2026 19:42:52 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/200947.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 21 Dec 2007 21:08:03 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Fri, 21 Dec 2007 21:08:03 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe gerade eine Denklblockade bei einer Architektur, die den Smart-Pointer std::tr1::shared_ptr verwendet.</p>
<p>Konkret handelt es sich um einen Interpreter, der aus einer Ausdrucks-Klassen-Hierarchie aufgebaut ist. Die abstrakte Basisklasse besitzt die Methode 'eval'. Diese Methode gibt ein 'shared_ptr&lt;value&gt;' zurück. 'value' selbst erbt von 'expression'. Das heißt, wenn man 'eval' auf einen value ausführt, soll eigentlich eine Referenz auf 'this' zurückgegeben werden. Das ist natürlich aber illegal, weil das Objekt dadurch zu oft zerstört wird. Ich will ungern einen rohen Zeiger zurückgeben, weil es gut sein könnte, dass die 'eval'-Methode für einige Objekte tatsächlich neue Objekte erzeugen muss (das ist sogar der Normalfall). Um diese verwalten zu können, muss ich ja wohl oder übel einen Smart-Pointer zurückgeben.</p>
<p>Kann jemand das Dilemma für mich lösen?</p>
<p>Nochmal zur Verdeutlichung, folgende Beispielklassen (ohne Konstruktoren und sonstiges Beiwerk):</p>
<pre><code class="language-cpp">struct value : public expression { /* … */ };

// Variante mit Smart-Pointer:

struct int_value : public value {
    int m_value;
    shared_ptr&lt;value&gt; eval(context&amp; ctx) {
        shared_ptr&lt;value&gt; ret(this);
        return ret;
    }
};

context ctx;
int_value my_int(42);
shared_ptr&lt;value&gt; result = my_int.eval(ctx);
// BANG: Doppelte Deallokation des aktuellen Objekts.

// Variante ohne Smart-Pointer:

struct int_addition : public binary_expression {
    expression* left;
    expression* right;

    value* eval(context&amp; ctx) {
        value* leftvalue = left.eval(ctx);
        value* rightvalue = right.eval(ctx);
        value* ret = new int_value(ctx.as_int(leftvalue)  + ctx.as_int(rightvalue));
        return ret;
    }
};

context ctx;
int_value x(42);
int_value y(23);
int_addition add(&amp;x, &amp;y);
value* z = add.eval(ctx);
// BANG: Speicherleck.
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1424622</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424622</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Fri, 21 Dec 2007 21:08:03 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Fri, 21 Dec 2007 21:20:26 GMT]]></title><description><![CDATA[<p>Probier mal folgendes:</p>
<pre><code class="language-cpp">struct int_value : public value, public std::tr1::enable_shared_from_this&lt;int_value&gt;
{
   // ...
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1424630</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424630</guid><dc:creator><![CDATA[Artchi]]></dc:creator><pubDate>Fri, 21 Dec 2007 21:20:26 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Fri, 21 Dec 2007 21:44:08 GMT]]></title><description><![CDATA[<p>Hi Artchie,</p>
<p>mehrere Dinge.</p>
<p>Erstens: Danke, klasse. Da hat ja jemand die Arbeit für mich gemacht. <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>
<p>Zweitens: Denkblockade? Hm, das sieht eher nach einem echten (zum Glück gelösten) Problem aus.</p>
<p>Drittens: Ich bin mir nicht sicher, dass ich den Quellcode der Klasse verstehe: '_internal_weak_this' wird ja nur default-initialisiert. Woher bekommt es den korrekten Zeigerwert?</p>
<p>Viertens: Funktioniert das auch, wenn ich nur (!) die Basisklasse 'value' von dieser Hilfsklasse erben lasse? Dann stimmt zwar genaugenommen der Templatetyp für die abgeleiteten Klassen nicht, aber dieser Typ ist für den 'shared_ptr' ja eigentlich (!) nur für die Deallokation wichtig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1424640</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424640</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Fri, 21 Dec 2007 21:44:08 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Sat, 22 Dec 2007 01:09:34 GMT]]></title><description><![CDATA[<p>Drittens:</p>
<p>_internal_weak_this wird von der shared_ptr Klasse initialisiert, wenn man das Objekt das erste mal einem shared_ptr übergibt (was ja auch laut doku voraussetzung dafür ist dass shared_from_this() funktioniert):</p>
<pre><code class="language-cpp">template&lt;class T&gt; class shared_ptr
{
// ...
    template&lt;class Y&gt;
    explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
    {
        boost::detail::sp_enable_shared_from_this( pn, p, p );
    }
// ...
};

// dieser overload greift zuletzt, wegen &quot;...&quot;
inline void sp_enable_shared_from_this( shared_count const &amp; /*pn*/, ... )
{
}

// dieser overload greift wenn die klasse von boost::enable_shared_from_this&lt;T&gt; abgeleitet ist
template&lt;class T, class Y&gt; void sp_enable_shared_from_this( shared_count const &amp; pn, boost::enable_shared_from_this&lt;T&gt; const * pe, Y const * px )
{
    if(pe != 0) pe-&gt;_internal_weak_this._internal_assign(const_cast&lt;Y*&gt;(px), pn);
}
</code></pre>
<p>Deswegen muss man auch public von enable_shared_from_this&lt;T&gt; ableiten oder shared_ptr zum friend machen <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>
<p>Viertens:</p>
<p>Ja, es reicht wenn du &quot;value&quot; von enable_shared_from_this ableitest, bloss musst du den Returnwert von shared_from_this dann natürlich immer casten. Ich würde es aber so machen, also die Basisklasse von enable_shared_from_this ableiten und casten - ist denke ich die bessere Lösung.<br />
(Falls du nicht public ableitest müsstest du natürlich mehrere shared_ptr&lt;T&gt; zum friend machen, halt für jede abgeleitete Klasse, sonst haut die implizite Konvertierung nach enable_shared_from_this&lt;value&gt;* nichtmehr hin.)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1424686</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424686</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 22 Dec 2007 01:09:34 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Sat, 22 Dec 2007 09:50:14 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>_internal_weak_this wird von der shared_ptr Klasse initialisiert, wenn man das Objekt das erste mal einem shared_ptr übergibt (was ja auch laut doku voraussetzung dafür ist dass shared_from_this() funktioniert):</p>
</blockquote>
<p>Ups, Danke. Habe ich irgendwie überlesen.</p>
<p>Ich muss aber ehrlich sagen, dass mir das ganze ein wenig missfällt. Ich muss mal schauen, ob ich da nicht vielleicht doch einen anderen Mechanismus der Speicherverwaltung verwende.</p>
<blockquote>
<p>Ja, es reicht wenn du &quot;value&quot; von enable_shared_from_this ableitest, bloss musst du den Returnwert von shared_from_this dann natürlich immer casten.</p>
</blockquote>
<p>Nicht mal: So, wie ich das zur Zeit sehe, bräuchte ich diese Art der Rückgabe lediglich für 'eval', und der Rückgabewert dieser Methode ist sowieso ein Zeiger auf 'value'.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1424720</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424720</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Sat, 22 Dec 2007 09:50:14 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Sat, 22 Dec 2007 18:16:48 GMT]]></title><description><![CDATA[<p>Naja, du kannst counted-body (boost::intrusive_ptr) statt counted-handle (boost::shared_ptr) verwenden.<br />
Dadurch entfällt der ganze shared_from_this() Tanz, andrerseits gibt's dann auch keine weak_ptr mehr.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1424904</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424904</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Sat, 22 Dec 2007 18:16:48 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Sat, 22 Dec 2007 19:33:01 GMT]]></title><description><![CDATA[<p>Hi Hustbaer,</p>
<p>schick. Allerdings würde ich dann tendenziell eher gleich operator new geeignet überladen. Muss mal schauen, was sich da später am besten eignet. Ich arbeite jetzt erst mal mit den referenzgezählten Zeigern weiter, die notwendige Änderung ist dann relativ transparent, d.h. da mache ich mir jetzt noch keinen Kopf drum. Aber ich halte es irgendwie für'n schlechtes Zeichen, wenn ich quasi ganz Zu Anfang schon über so fundamentale Probleme stolpere. <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="😃"
    /> Zeugt irgendwie von einem nicht genügende durchdachten Design.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1424936</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1424936</guid><dc:creator><![CDATA[Konrad Rudolph]]></dc:creator><pubDate>Sat, 22 Dec 2007 19:33:01 GMT</pubDate></item><item><title><![CDATA[Reply to Rückgabe von &#x27;this&#x27; als Smart-Pointer on Tue, 25 Dec 2007 06:27:21 GMT]]></title><description><![CDATA[<p>Shared ownership ist immer irgendwie doof, deswegen finden ja auch alle (ok, viele) boost::shared_ptr so geil.<br />
An einigen Stellen kann aber eben boost::intrusive_ptr auch sehr nützlich sein, bzw. evtl. ganz eigene Konstrukte (Manager Klassen etc.).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1425806</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1425806</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 25 Dec 2007 06:27:21 GMT</pubDate></item></channel></rss>