<?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[std::vector von MSVC]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich nutze Visual Studio 2013 EE und konnte ein merkwürdiges Verhalten feststellen. Ich habe einen Allocator-Wrapper geschrieben, der die durchgeführten Aktionen festhält und an einen darunterliegenden Allocator weiterleitet. Folgender Code:</p>
<pre><code>{
		typedef al::LoggingAllocator&lt;int, std::allocator&gt; AllocT;
		std::vector&lt;int, AllocT&gt; Foo(AllocT(&amp;std::cout));
		std::cout &lt;&lt; Foo.size() &lt;&lt; ':' &lt;&lt; Foo.capacity() &lt;&lt; '\n';
	}
</code></pre>
<p>Die Ausgabe ist die folgende (* bedeutet, dass die Aktion den Allocator betrifft, sprich, dass der Allocator konstruiert wurde und nicht ein Objekt):</p>
<pre><code>LoggingAllocator&lt;int&gt; Id 0: * Constructed from LoggingDestination (0F1AC1B0)
LoggingAllocator&lt;int&gt; Id 1: * Copy-constructed (0)
LoggingAllocator&lt;int&gt; Id 2: * Copy-constructed (1)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: * Constructed from another LoggingAllocator&lt;&gt; (2)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: Allocating a block of 1 element(s)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3:    success: 0038BA88
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: Copy-constructing an object (0038BA88)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: * Destructed
LoggingAllocator&lt;int&gt; Id 1: * Destructed
LoggingAllocator&lt;int&gt; Id 0: * Destructed
0:0
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: * Constructed from another LoggingAllocator&lt;&gt; (2)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: Destroying an object (0038BA88)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: Deallocating a block (0038BA88) of 1 element(s)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: * Destructed
LoggingAllocator&lt;int&gt; Id 2: * Destructed
</code></pre>
<p><s>Dabei ist die Ausgabe beim Debug-Build gleich wie beim Release-Build.</s></p>
<p>Meine Fragen:<br />
1. Darf der Container Objekte mit einem anderen Allocator löschen / zerstören als mit demjenigen, mit welchem sie alloziert / konstruiert wurden?<br />
2. Darf der Container sein internes Zeug ( <code>std::_Container_proxy</code> ) mit seinem Allocator anfordern?<br />
3. Wozu braucht die MSVC-Implementierung dynamischen Speicher für einen leeren Container? <s>Und wieso das selbst im Release-Build? Ich wurde aus dem Code nicht so richtig schlau auf die Schnelle, vielleicht weiss da jemand mehr dazu.</s></p>
<p>Gruss</p>
<p>Edit: Aufgrund meines menschlichen Versagens war das, was ich über die Release-Builds gesagt habe, nicht ganz korrekt.<br />
Ausgabe vom Release-Build:</p>
<pre><code>LoggingAllocator&lt;int&gt; Id 0: * Constructed from LoggingDestination (6B856198)
LoggingAllocator&lt;int&gt; Id 1: * Copy-constructed (0)
LoggingAllocator&lt;int&gt; Id 0: * Destructed
0:0
LoggingAllocator&lt;int&gt; Id 1: * Destructed
</code></pre>
<p>Edit 2:<br />
Bei Fundamentals ruft <code>std::vector</code>  <code>AllocatorT::destroy</code> gar nicht auf vor <code>AllocatorT::deallocate</code> (resp. das Äquivalent aus <code>std::allocator_traits</code> ). Darf er das?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/331389/std-vector-von-msvc</link><generator>RSS for Node</generator><lastBuildDate>Fri, 01 May 2026 19:16:24 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/331389.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 26 Feb 2015 11:04:45 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to std::vector von MSVC on Thu, 26 Feb 2015 12:41:25 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich nutze Visual Studio 2013 EE und konnte ein merkwürdiges Verhalten feststellen. Ich habe einen Allocator-Wrapper geschrieben, der die durchgeführten Aktionen festhält und an einen darunterliegenden Allocator weiterleitet. Folgender Code:</p>
<pre><code>{
		typedef al::LoggingAllocator&lt;int, std::allocator&gt; AllocT;
		std::vector&lt;int, AllocT&gt; Foo(AllocT(&amp;std::cout));
		std::cout &lt;&lt; Foo.size() &lt;&lt; ':' &lt;&lt; Foo.capacity() &lt;&lt; '\n';
	}
</code></pre>
<p>Die Ausgabe ist die folgende (* bedeutet, dass die Aktion den Allocator betrifft, sprich, dass der Allocator konstruiert wurde und nicht ein Objekt):</p>
<pre><code>LoggingAllocator&lt;int&gt; Id 0: * Constructed from LoggingDestination (0F1AC1B0)
LoggingAllocator&lt;int&gt; Id 1: * Copy-constructed (0)
LoggingAllocator&lt;int&gt; Id 2: * Copy-constructed (1)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: * Constructed from another LoggingAllocator&lt;&gt; (2)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: Allocating a block of 1 element(s)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3:    success: 0038BA88
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: Copy-constructing an object (0038BA88)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 3: * Destructed
LoggingAllocator&lt;int&gt; Id 1: * Destructed
LoggingAllocator&lt;int&gt; Id 0: * Destructed
0:0
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: * Constructed from another LoggingAllocator&lt;&gt; (2)
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: Destroying an object (0038BA88)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: Deallocating a block (0038BA88) of 1 element(s)...
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4:    success
LoggingAllocator&lt;struct std::_Container_proxy&gt; Id 4: * Destructed
LoggingAllocator&lt;int&gt; Id 2: * Destructed
</code></pre>
<p><s>Dabei ist die Ausgabe beim Debug-Build gleich wie beim Release-Build.</s></p>
<p>Meine Fragen:<br />
1. Darf der Container Objekte mit einem anderen Allocator löschen / zerstören als mit demjenigen, mit welchem sie alloziert / konstruiert wurden?<br />
2. Darf der Container sein internes Zeug ( <code>std::_Container_proxy</code> ) mit seinem Allocator anfordern?<br />
3. Wozu braucht die MSVC-Implementierung dynamischen Speicher für einen leeren Container? <s>Und wieso das selbst im Release-Build? Ich wurde aus dem Code nicht so richtig schlau auf die Schnelle, vielleicht weiss da jemand mehr dazu.</s></p>
<p>Gruss</p>
<p>Edit: Aufgrund meines menschlichen Versagens war das, was ich über die Release-Builds gesagt habe, nicht ganz korrekt.<br />
Ausgabe vom Release-Build:</p>
<pre><code>LoggingAllocator&lt;int&gt; Id 0: * Constructed from LoggingDestination (6B856198)
LoggingAllocator&lt;int&gt; Id 1: * Copy-constructed (0)
LoggingAllocator&lt;int&gt; Id 0: * Destructed
0:0
LoggingAllocator&lt;int&gt; Id 1: * Destructed
</code></pre>
<p>Edit 2:<br />
Bei Fundamentals ruft <code>std::vector</code>  <code>AllocatorT::destroy</code> gar nicht auf vor <code>AllocatorT::deallocate</code> (resp. das Äquivalent aus <code>std::allocator_traits</code> ). Darf er das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444426</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444426</guid><dc:creator><![CDATA[Fytch]]></dc:creator><pubDate>Thu, 26 Feb 2015 12:41:25 GMT</pubDate></item><item><title><![CDATA[Reply to std::vector von MSVC on Thu, 26 Feb 2015 15:03:27 GMT]]></title><description><![CDATA[<p>asfdlol schrieb:</p>
<blockquote>
<p>1. Darf der Container Objekte mit einem anderen Allocator löschen / zerstören als mit demjenigen, mit welchem sie alloziert / konstruiert wurden?</p>
</blockquote>
<p>Soweit ich weiss war das immer erlaubt, sofern der andere Allocator als Kopie des ursprünglichen Allocators erstellt wurde.</p>
<p>asfdlol schrieb:</p>
<blockquote>
<p>2. Darf der Container sein internes Zeug ( <code>std::_Container_proxy</code> ) mit seinem Allocator anfordern?</p>
</blockquote>
<p>Ich schätze ja. Bin aber kein Experte auf dem Gebite. Was sicher OK ist, ist über ::rebind andere Allocator-Typen zu erzeugen, und damit dann z.B. einen Allocator für Tree-Nodes zu erzeugen (die dann ja üblicherweise das User-Item mit enthalten).</p>
<p>asfdlol schrieb:</p>
<blockquote>
<p>3. Wozu braucht die MSVC-Implementierung dynamischen Speicher für einen leeren Container? <s>Und wieso das selbst im Release-Build? Ich wurde aus dem Code nicht so richtig schlau auf die Schnelle, vielleicht weiss da jemand mehr dazu.</s></p>
</blockquote>
<p>Muss ich mir angucken. Kann mir aber nicht vorstellen dass ein leerer MSVC vector dynamisch Speicher anfordert. Das wäre ja ganz krass böse.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444440</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444440</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Thu, 26 Feb 2015 15:03:27 GMT</pubDate></item><item><title><![CDATA[Reply to std::vector von MSVC on Fri, 27 Feb 2015 04:25:36 GMT]]></title><description><![CDATA[<p>OK. Also.</p>
<p>Ohne Iterator-Debugging macht MSVC's vector genau 0 Allokationen so lange man nix rein tut (=Default im Release Build). So wie es sein soll.<br />
Mit Iterator-Debugging erzeugt er immer dynamisch einen <code>_Container_proxy</code> .</p>
<p>Dieser ist für's Iterator-Debugging nötig und speichert den Zeiger auf den ersten Iterator des Containers.<br />
Damit <code>swap</code> O(1) bleiben kann muss der <code>_Container_proxy</code> dynamisch angefordert werden. (Die Iteratoren haben ihrerseits ja einen Zeiger auf den <code>_Container_proxy</code> , und wenn man den <code>_Container_proxy</code> nicht mittauschen könnte, dann müssten diese Zeiger in ALLEN Iteratoren umgeschrieben werden.)</p>
<p>Was der Grund ist dass trotz leerem <code>vector</code> der <code>_Container_proxy</code> sofort erzeugt wird, kann ich nicht sagen, so genau hab ich mir den Code auch nicht angesehen.<br />
Könnte sein Faulheit, könnte aber genau so gut sein dass das Erlauben eines nicht-vorhandenen <code>_Container_proxy</code> an vielen Stellen Checks/Sonderbehandlungen erfordern würde, so dass es im Endeffekt bei durchschnittlichen Programmen sogar schneller den Proxy einfach immer zu erzeugen.</p>
<p>asfdlol schrieb:</p>
<blockquote>
<p>Bei Fundamentals ruft <code>std::vector</code>  <code>AllocatorT::destroy</code> gar nicht auf vor <code>AllocatorT::deallocate</code> (resp. das Äquivalent aus <code>std::allocator_traits</code> ). Darf er das?</p>
</blockquote>
<p>Wieso nicht?</p>
<p>Du darfst Objekte in C++ ohne weiteres dadurch zerstören dass du einfach ihren Speicher freigibst.<br />
Bedingung dafür ist bloss dass das korrekte Funktionieren des Programms nicht davon abhängt dass der Dtor ausgeführt wird. Oder anders gesagt: der Dtor ist, abgesehen von den vielen Fällen wo C++ ihn automatisch für dich aufruft, eine ganz normale Funktion.<br />
&quot;Magic&quot; wie die des Ctor, der aus einem Speicherbereich, voll mit lauter Schrott aus alten Flippern, ein Objekt einer Klasse T erzeugen kann, das dann danach auch als T angesprochen werden darf, gibt es beim Dtor keine. *</p>
<p>D.h. wenn du die Klasse deren Objekt du durch &quot;einfach freigeben&quot; zerstören willst kennst, und weisst dass die im Dtor nix tut, dann geht das OK.</p>
<p>Zumindest ist das bei normalen, über new/placement new erzeugten Objekten so. Wenn es da für über Allokatoren angeforderte Objekte keine Spezialregel gibt, dann würde ich die &quot;üblichen&quot; sonst geltenden Regeln auch da anwenden, und das würde heissen: ja, ist OK.</p>
<p>*: Du darfst in C++ ein Objekt auch einfach dadruch zerstören dass du es mit 'was anderem überschreibst. Natürlich wieder nur unter der Voraussetzung dass die Ausführung des Dtors wirklich unnötig ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444507</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 27 Feb 2015 04:25:36 GMT</pubDate></item><item><title><![CDATA[Reply to std::vector von MSVC on Fri, 27 Feb 2015 09:32:25 GMT]]></title><description><![CDATA[<p>Danke für die Antwort, sehr aufschlussreich. <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>
<p>hustbaer schrieb:</p>
<blockquote>
<p>asfdlol schrieb:</p>
<blockquote>
<p>2. Darf der Container sein internes Zeug ( <code>std::_Container_proxy</code> ) mit seinem Allocator anfordern?</p>
</blockquote>
<p>Ich schätze ja. Bin aber kein Experte auf dem Gebite. Was sicher OK ist, ist über ::rebind andere Allocator-Typen zu erzeugen, und damit dann z.B. einen Allocator für Tree-Nodes zu erzeugen (die dann ja üblicherweise das User-Item mit enthalten).</p>
</blockquote>
<p>Ach ja, selbstverständlich... wie konnte ich das bloss vergessen...</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>asfdlol schrieb:</p>
<blockquote>
<p>Bei Fundamentals ruft <code>std::vector</code>  <code>AllocatorT::destroy</code> gar nicht auf vor <code>AllocatorT::deallocate</code> (resp. das Äquivalent aus <code>std::allocator_traits</code> ). Darf er das?</p>
</blockquote>
<p>Wieso nicht?</p>
</blockquote>
<p>Irgendwie hatte ich das Gefühl, dass auch zu jedem Ctor-Aufruf auch ein Dtor-Aufruf gehört, oder zumindest zu jedem <code>construct</code> ein <code>destroy</code> . Meine Intuition behielt wohl nicht Recht.</p>
<p>Nach meinem Verständnis nachdem ich gelesen habe, was du geschrieben hast, könnte man mit <code>std::is_trivially_destructible</code> testen, ob ein <code>destroy</code> -Aufruf vonnöten ist, ja?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444525</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444525</guid><dc:creator><![CDATA[Fytch]]></dc:creator><pubDate>Fri, 27 Feb 2015 09:32:25 GMT</pubDate></item><item><title><![CDATA[Reply to std::vector von MSVC on Fri, 27 Feb 2015 11:49:19 GMT]]></title><description><![CDATA[<p>Ja, mit <code>std::is_trivially_destructible</code> müsste es wohl gehen.<br />
Wobei das vermutlich auch nur bei so Sachen wie Pool-Allokatoren was bringen würde, wenn man den ganzen Pool wegwerfen kann ohne die Dtors vorher aufzurufen. Wenn überhaupt.<br />
Der Compiler weiss ja dann auch dass <code>std::is_trivially_destructible == true</code> , und dann erzeugt er einfach keinen code für das <code>p-&gt;~T()</code> ;</p>
<p>D.h. es ist vermutlich nicht super sinnvoll über solche Optimierungen wirklich nachzudenken. Aber in C++ ist ja einiges &quot;legal&quot; was kaum jemals bis gar nicht sinnvoll ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2444533</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2444533</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Fri, 27 Feb 2015 11:49:19 GMT</pubDate></item></channel></rss>