<?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[Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.)]]></title><description><![CDATA[<p>Hallo zusammen!</p>
<p>ich suche nach weiteren Lösungsansätzen für ein Problem bei dem ich vermeiden möchte, die Lösung &quot;zu Fuß&quot; zu implementieren und bei dem mir gerade die Ideen ausgehen.</p>
<p>Vielleicht fällt euch ja etwas ein?</p>
<p><strong>Problem:</strong></p>
<p>Ich möchte ein Array oder eine vergleichbare Datenstruktur variabler Länge möglichst effizient mittels Reference Counting verwalten.<br />
Die Länge der Arrays ist erst zur Laufzeit bekannt, und soll auch veränderbar sein. Im Prinzip suche ich so etwas:</p>
<pre><code>T* a = new T[N];
...
delete [] a;
a = new T[M];
</code></pre>
<p>... nur dass das Array eben über einen <code>shared_ptr</code> oder etwas Vergleichbarem verwaltet wird.<br />
Ferner gibt es noch folgende Anforderung, welche viele naheliegende Lösungen nicht praktikabel macht:</p>
<p>Minimaler Overhead: Mit Ausnahme der atomaren Operationen und den zusätzlichen Speicher für das Reference Counting soll die Datenstruktur die selben Ausführungs- und Speicherzugriffscharakteristiken haben wie o.g. <code>new</code> / <code>delete</code> -Konstrukt haben.<br />
Insbesondere: Keine zusätzlichen Allokationen und Cache-freudlicher Zugriff auf die Elemente (d.h. keine load-Operationen auf Speicherbereiche in deren Nachbarschaft keine Array-Elemente liegen).</p>
<p><strong>Bisherige Ansätze:</strong></p>
<p><strong>1.</strong></p>
<pre><code>std::shared_ptr&lt;std::vector&lt;T&gt;&gt;
</code></pre>
<p>Leider ungeeignet, da der Zugriff auf die Elemente eine zusätzliche Dereferenzierung erfordert.<br />
std::shared_ptr und std::vector sind meines wissens so oder ähnlich implementiert:</p>
<pre><code>class shared_ptr
{
   ...
   T* object;
   ...
}

class vector
{
   ...
   T* elements;
   ...
}
</code></pre>
<p>d.h. um auf ein Element von <code>vector</code> zuzugreifen muss zunächst <code>object</code> und dann <code>elements</code> dereferenziert werden, es wird also oft eine Cache-Line geladen um lediglich an den <code>elements</code> -Pointer zu gelangen (und eventuell die Länge des Vektors), ohne dass ich beim Zugriff auf die eigentlichen Elemente davon weiter profitieren könnte. Zugegeben, beim Durchlaufen besonders langer Arrays wird sich das zusätzliche Dereferenzieren wahrscheinlich amortisieren, ich suche aber nach einer Lösung die diesen Overhead dennoch vermeidet.</p>
<p><strong>2.</strong></p>
<pre><code>std::shared_ptr&lt;std::array&lt;T, N&gt;&gt;
</code></pre>
<p>Ungeeignet, da die Länge des Arrays während des Kompilierens bekannt sein muss und diese Teil des Typs ist (soll zugewiesen werden können, auch wenn linke und rechte Seite der Zuweisung unterschiedliche Array-Längen haben)</p>
<p><strong>3.</strong> <code>std::shared_ptr&lt;T&gt;</code> mit Custom-Deleter:</p>
<pre><code>std::shared_ptr&lt;T&gt; a(new T[N], std::default_delete&lt;T[]&gt;());
</code></pre>
<p>... sieht nach einer guten Lösung aus, benötigt aber 2 Allokationen ( <code>new T[N]</code> und Kontrollblock von <code>shared_ptr</code> , Exception-safety erstmal außen vor) und der Kontrollblock ist im Speicher nicht mit den Elementen den benachbart.<br />
<code>std::make_shared</code> wäre die ideale Lösung, unterstützt allerdings leider nicht die Konstruktion von Arrays in der o.g. Form <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Falls jemand mit so etwas schonmal Erfahrungen gesammelt hat, und einen guten Lösungsansatz hat, wäre ich dankbar. Das per Hand zu implementieren ist ein ziemlicher Schlepp den ich gerne vermeiden würde <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>Gruss,<br />
Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/330632/reference-counted-array-variabler-länge-mit-minimalem-overhead-shared_ptr-o-ä</link><generator>RSS for Node</generator><lastBuildDate>Thu, 02 Jul 2026 22:50:30 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/330632.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 19 Jan 2015 18:35:29 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 18:35:29 GMT]]></title><description><![CDATA[<p>Hallo zusammen!</p>
<p>ich suche nach weiteren Lösungsansätzen für ein Problem bei dem ich vermeiden möchte, die Lösung &quot;zu Fuß&quot; zu implementieren und bei dem mir gerade die Ideen ausgehen.</p>
<p>Vielleicht fällt euch ja etwas ein?</p>
<p><strong>Problem:</strong></p>
<p>Ich möchte ein Array oder eine vergleichbare Datenstruktur variabler Länge möglichst effizient mittels Reference Counting verwalten.<br />
Die Länge der Arrays ist erst zur Laufzeit bekannt, und soll auch veränderbar sein. Im Prinzip suche ich so etwas:</p>
<pre><code>T* a = new T[N];
...
delete [] a;
a = new T[M];
</code></pre>
<p>... nur dass das Array eben über einen <code>shared_ptr</code> oder etwas Vergleichbarem verwaltet wird.<br />
Ferner gibt es noch folgende Anforderung, welche viele naheliegende Lösungen nicht praktikabel macht:</p>
<p>Minimaler Overhead: Mit Ausnahme der atomaren Operationen und den zusätzlichen Speicher für das Reference Counting soll die Datenstruktur die selben Ausführungs- und Speicherzugriffscharakteristiken haben wie o.g. <code>new</code> / <code>delete</code> -Konstrukt haben.<br />
Insbesondere: Keine zusätzlichen Allokationen und Cache-freudlicher Zugriff auf die Elemente (d.h. keine load-Operationen auf Speicherbereiche in deren Nachbarschaft keine Array-Elemente liegen).</p>
<p><strong>Bisherige Ansätze:</strong></p>
<p><strong>1.</strong></p>
<pre><code>std::shared_ptr&lt;std::vector&lt;T&gt;&gt;
</code></pre>
<p>Leider ungeeignet, da der Zugriff auf die Elemente eine zusätzliche Dereferenzierung erfordert.<br />
std::shared_ptr und std::vector sind meines wissens so oder ähnlich implementiert:</p>
<pre><code>class shared_ptr
{
   ...
   T* object;
   ...
}

class vector
{
   ...
   T* elements;
   ...
}
</code></pre>
<p>d.h. um auf ein Element von <code>vector</code> zuzugreifen muss zunächst <code>object</code> und dann <code>elements</code> dereferenziert werden, es wird also oft eine Cache-Line geladen um lediglich an den <code>elements</code> -Pointer zu gelangen (und eventuell die Länge des Vektors), ohne dass ich beim Zugriff auf die eigentlichen Elemente davon weiter profitieren könnte. Zugegeben, beim Durchlaufen besonders langer Arrays wird sich das zusätzliche Dereferenzieren wahrscheinlich amortisieren, ich suche aber nach einer Lösung die diesen Overhead dennoch vermeidet.</p>
<p><strong>2.</strong></p>
<pre><code>std::shared_ptr&lt;std::array&lt;T, N&gt;&gt;
</code></pre>
<p>Ungeeignet, da die Länge des Arrays während des Kompilierens bekannt sein muss und diese Teil des Typs ist (soll zugewiesen werden können, auch wenn linke und rechte Seite der Zuweisung unterschiedliche Array-Längen haben)</p>
<p><strong>3.</strong> <code>std::shared_ptr&lt;T&gt;</code> mit Custom-Deleter:</p>
<pre><code>std::shared_ptr&lt;T&gt; a(new T[N], std::default_delete&lt;T[]&gt;());
</code></pre>
<p>... sieht nach einer guten Lösung aus, benötigt aber 2 Allokationen ( <code>new T[N]</code> und Kontrollblock von <code>shared_ptr</code> , Exception-safety erstmal außen vor) und der Kontrollblock ist im Speicher nicht mit den Elementen den benachbart.<br />
<code>std::make_shared</code> wäre die ideale Lösung, unterstützt allerdings leider nicht die Konstruktion von Arrays in der o.g. Form <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Falls jemand mit so etwas schonmal Erfahrungen gesammelt hat, und einen guten Lösungsansatz hat, wäre ich dankbar. Das per Hand zu implementieren ist ein ziemlicher Schlepp den ich gerne vermeiden würde <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>Gruss,<br />
Finnegan</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438454</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438454</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 19 Jan 2015 18:35:29 GMT</pubDate></item><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 18:44:21 GMT]]></title><description><![CDATA[<p>Evtl. könntest du mit allocate_shared tricksen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438460</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438460</guid><dc:creator><![CDATA[Nathan]]></dc:creator><pubDate>Mon, 19 Jan 2015 18:44:21 GMT</pubDate></item><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 19:19:19 GMT]]></title><description><![CDATA[<p>Was ist mit <a href="http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/intrusive_ptr.html" rel="nofollow">http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/intrusive_ptr.html</a> ?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438470</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438470</guid><dc:creator><![CDATA[Intr Usoff]]></dc:creator><pubDate>Mon, 19 Jan 2015 19:19:19 GMT</pubDate></item><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 20:22:41 GMT]]></title><description><![CDATA[<p>@Intr Usoff<br />
Intrusive-Pointer sollten eine gute Möglichkeit sein, wenn die Array-Elemente immer PODs sind.<br />
Mit nicht-POD Typen wüsste ich auf die Schnelle aber nicht wie man das anstellen soll. Ausser halt wieder viel Code selbst zu schreiben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438487</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438487</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 19 Jan 2015 20:22:41 GMT</pubDate></item><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 20:43:26 GMT]]></title><description><![CDATA[<p>Finnegan schrieb:</p>
<blockquote>
<p>Zugegeben, beim Durchlaufen besonders langer Arrays wird sich das zusätzliche Dereferenzieren wahrscheinlich amortisieren, ich suche aber nach einer Lösung die diesen Overhead dennoch vermeidet.</p>
</blockquote>
<p>Wäre SmallVector eine Option? Also immer Speicher für ca. 16 Elemente bereithalten und wenn das überschritten wird, dynamisch Speicher anfordern. Nicht maximal effizient, aber dafür einfach.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438493</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438493</guid><dc:creator><![CDATA[SSOne]]></dc:creator><pubDate>Mon, 19 Jan 2015 20:43:26 GMT</pubDate></item><item><title><![CDATA[Reply to Reference-Counted Array variabler Länge mit minimalem Overhead (shared_ptr, o.ä.) on Mon, 19 Jan 2015 21:48:37 GMT]]></title><description><![CDATA[<p>Nathan schrieb:</p>
<blockquote>
<p>Evtl. könntest du mit allocate_shared tricksen.</p>
</blockquote>
<p>Intr Usoff schrieb:</p>
<blockquote>
<p>Was ist mit <a href="http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/intrusive_ptr.html" rel="nofollow">http://www.boost.org/doc/libs/1_57_0/libs/smart_ptr/intrusive_ptr.html</a> ?</p>
</blockquote>
<p>Hey! Boost und <code>allocate_shared</code> waren die richtigen Stichworte, die mich auf die richtige Fährte gebracht haben (aus Boost 1.57-Doku):</p>
<pre><code>template&lt;class U&gt; 
    shared_ptr&lt;U&gt; make_shared(size_t size);
template&lt;class U, class A&gt; 
    shared_ptr&lt;U&gt; allocate_shared(const A&amp; allocator, size_t size);

    Returns: A shared_ptr to a value-initialized object of type T[size].

    Remarks: These overloads shall only participate in overload resolution when U is of the form T[].

    Examples:

        boost::shared_ptr&lt;int[]&gt; a1 = boost::make_shared&lt;int[]&gt;(size);
        boost::shared_ptr&lt;int[][2]&gt; a2 = boost::make_shared&lt;int[][2]&gt;(size);
</code></pre>
<p>Scheint so, als könne der <code>boost::shared_ptr</code> genau das was ich beim <code>std::shared_ptr</code> vermisst habe! Jetzt, wo so vieles aus Boost Einzug in die Standard Library gehalten hat, bin ich gar nicht mehr drauf gekommen, dass Boost auch einen <code>shared_ptr</code> hat. Ich werd's mal damit probieren <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 />
Vielen Dank jedenfalls!</p>
<p>Finnegan</p>
<p>P.S.: Jetzt ist es mir schon ein bisschen peinlich, dass ich das nicht vorher gefunden habe - diese Lösung habe ich sogar in den Suchmaschinenergebnissen übersehen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f644.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_rolling_eyes"
      title=":rolling_eyes:"
      alt="🙄"
    /> (Schande über mich, LMGTFY lasst grüssen). Sorry!<br />
BTW: Scheint sogar mit N3641 ein Standard-Proposal zu geben, in dem vorgeschlagen wird, das auch in <code>std</code> aufzunehmen. Könnte also sein, das sowas demnächst von Haus aus unterstützt wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2438508</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2438508</guid><dc:creator><![CDATA[Finnegan]]></dc:creator><pubDate>Mon, 19 Jan 2015 21:48:37 GMT</pubDate></item></channel></rss>