<?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::map und erase]]></title><description><![CDATA[<p>Hi.<br />
Laut dem Artikel im C++ Magazin über die STL (Teil 1) hat std::map eine automatische Speicherfreigabe. Heißt dass, das folgender Code so funktioniert und keinen Memoryleak erzeugt?</p>
<pre><code class="language-cpp">class CTest
{
public:
    void append(char *pszName);
    void remove(char *pszName);

private:
    std::map&lt;char*, CBla*, CmpStr&gt; m_mapTest;
};

void CTest::append(char *pszName)
{
    char *pszKey = new char[strlen(pszName) + 1];
    strcpy(pszKey, pszName);
    CBla *pBla = new CBla;

    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*&gt;(pszKey, pBla));
}

void CTest::remove(char *pszName)
{
    std::map&lt;char*, CBla*, CmpStr&gt;::iterator it = this-&gt;m_mapTest.find(pszName);

    if (it != this-&gt;m_mapTest.end())
    {
        this-&gt;m_mapTest.erase(it);
        // stimmt es nun, dass pBla und pszKey ab hier gelöscht sind?
    }
}
</code></pre>
<p>Eine zweite Frage: Wenn ich in einer Schleife bin, einen Eintrag lösche, ist der Iterator dann ungültig? Oder kann ich ihn trotzdem noch weiter verwenden zum inkrementieren? In etwa so:</p>
<pre><code class="language-cpp">void CTest::loop(void)
{
    for (std::map&lt;char*, CBla*, CmpStr&gt;::iterator it = this-&gt;m_mapTest.begin(); it != this-&gt;m_mapTest.end(); it++)
    {
        if (!strcmp(it-&gt;first, &quot;bla&quot;))
        {
            this-&gt;m_mapTest.erase(it);
            // hier nach schlägt it++ doch fehl, oder?
        }
    }
}
</code></pre>
<p>Gruß</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/260690/std-map-und-erase</link><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 23:43:59 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/260690.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 08 Feb 2010 14:19:34 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 14:40:41 GMT]]></title><description><![CDATA[<p>Hi.<br />
Laut dem Artikel im C++ Magazin über die STL (Teil 1) hat std::map eine automatische Speicherfreigabe. Heißt dass, das folgender Code so funktioniert und keinen Memoryleak erzeugt?</p>
<pre><code class="language-cpp">class CTest
{
public:
    void append(char *pszName);
    void remove(char *pszName);

private:
    std::map&lt;char*, CBla*, CmpStr&gt; m_mapTest;
};

void CTest::append(char *pszName)
{
    char *pszKey = new char[strlen(pszName) + 1];
    strcpy(pszKey, pszName);
    CBla *pBla = new CBla;

    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*&gt;(pszKey, pBla));
}

void CTest::remove(char *pszName)
{
    std::map&lt;char*, CBla*, CmpStr&gt;::iterator it = this-&gt;m_mapTest.find(pszName);

    if (it != this-&gt;m_mapTest.end())
    {
        this-&gt;m_mapTest.erase(it);
        // stimmt es nun, dass pBla und pszKey ab hier gelöscht sind?
    }
}
</code></pre>
<p>Eine zweite Frage: Wenn ich in einer Schleife bin, einen Eintrag lösche, ist der Iterator dann ungültig? Oder kann ich ihn trotzdem noch weiter verwenden zum inkrementieren? In etwa so:</p>
<pre><code class="language-cpp">void CTest::loop(void)
{
    for (std::map&lt;char*, CBla*, CmpStr&gt;::iterator it = this-&gt;m_mapTest.begin(); it != this-&gt;m_mapTest.end(); it++)
    {
        if (!strcmp(it-&gt;first, &quot;bla&quot;))
        {
            this-&gt;m_mapTest.erase(it);
            // hier nach schlägt it++ doch fehl, oder?
        }
    }
}
</code></pre>
<p>Gruß</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1852446</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852446</guid><dc:creator><![CDATA[theliquidwave]]></dc:creator><pubDate>Mon, 08 Feb 2010 14:40:41 GMT</pubDate></item><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 14:32:26 GMT]]></title><description><![CDATA[<p>theliquidwave schrieb:</p>
<blockquote>
<p>Laut dem Artikel im C++ Magazin über die STL (Teil 1) hat std::map eine automatische Speicherfreigabe. Heißt dass, das folgender Code so funktioniert und keinen Memoryleak erzeugt?</p>
</blockquote>
<p>Nein. Die Speicherfreigabe betrifft die Objekte selber (in deinem Fall die Zeiger), und nicht etwaige referenzierte Speicherbereiche. Oft speichert man ja auch nicht-besitzende Zeiger.</p>
<p>Nimm doch einfach <code>std::string</code> , dann bist du das Gefrickel los.</p>
<p>theliquidwave schrieb:</p>
<blockquote>
<p>Eine zweite Frage: Wenn ich in einer Schleife bin, einen Eintrag lösche, ist der Iterator dann ungültig? Oder kann ich ihn trotzdem noch weiter verwenden zum inkrementieren?</p>
</blockquote>
<p>Wenn ein Element gelöscht wird, sind alle Iteratoren, Zeiger und Referenzen auf dieses Element <strong>immer</strong> ungültig. Du kannst über assoziative STL-Container wie folgt iterieren:</p>
<pre><code class="language-cpp">for (bla_map::iterator it = map.begin(), end = map.end(); it != end; /* nichts */)
{
    if (/* Element hat es nicht verdient zu leben */)
        map.erase(it++)
    else
        ++it;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1852455</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852455</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 08 Feb 2010 14:32:26 GMT</pubDate></item><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 14:30:30 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Du kannst über sequenzielle STL-Container wie folgt iterieren:</p>
<pre><code class="language-cpp">for (bla_map::iterator it = map.begin(), end = map.end(); it != end; /* nichts */)
{
    if (/* Element hat es nicht verdient zu leben */)
        map.erase(it++)
    else
        ++it;
}
</code></pre>
</blockquote>
<p>std::map ist kein sequenzieller Container, sondern ein assoziativer.</p>
<p>Und: man kann gerade über einen (sehr wichtigen) sequenziellen Container *nicht* so drüberiterieren, nämlich über std::vector.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1852460</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852460</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 08 Feb 2010 14:30:30 GMT</pubDate></item><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 14:32:33 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p>std::map ist kein sequenzieller Container, sondern ein assoziativer.</p>
</blockquote>
<p>Klar, ich meinte natürlich assoziativ. Danke für die Anmerkung, habe es korrigiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1852463</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852463</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 08 Feb 2010 14:32:33 GMT</pubDate></item><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 14:42:21 GMT]]></title><description><![CDATA[<p>Hi.<br />
Danke!</p>
<p>Das heißt, ich muss pBla und pszKey (bzw. wenn ich dann std::string benutze nur pBla) selber löschen, richtig?</p>
<p>Zum iterieren: Folgendes Beispiel ist korrekt?</p>
<pre><code class="language-cpp">void CTest::loop(void)
{
    for (std::map&lt;char*, CBla*, CmpStr&gt;::iterator it = this-&gt;m_mapTest.begin(); it != this-&gt;m_mapTest.end(); )
    {
        std::cout &lt;&lt; it-&gt;first;

        if (!strcmp(it-&gt;first, &quot;test3&quot;))
        {
            delete[] it-&gt;first;
            delete it-&gt;second;

            this-&gt;m_mapTest.erase(it);

            std::cout &lt;&lt; &quot; (deleted)&quot;;
        }
        else
        {
            it++;
        }

        std::cout &lt;&lt; std::endl;
    }
}

void CTest::insert(void)
{
    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*, CmpStr&gt;(&quot;test1&quot;, new CBla));
    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*, CmpStr&gt;(&quot;test2&quot;, new CBla));
    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*, CmpStr&gt;(&quot;test3&quot;, new CBla));
    this-&gt;m_mapTest.insert(std::pair&lt;char*, CBla*, CmpStr&gt;(&quot;test4&quot;, new CBla));
}
</code></pre>
<p>Ausgabe wäre dann also:</p>
<pre><code>test1
test2
test3 (deleted)
test4
</code></pre>
<p>Und alles ist gelöscht (kein Memoryleak).</p>
<p>Edit @ Nexus: Kann es sein, dass dein Beispiel dann fehlschlagen würde? Ich dachte das Ende der Map verändert sich, wenn ein neues Item eingefügt oder ein anderes gelöscht wird, bei deinem wird aber immer auf das gleiche Element verwiesen (beim Vergleich in der for-Schleife).</p>
<p>Gruß &amp; sorry wegen der vielen Fragerei <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/1852469</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852469</guid><dc:creator><![CDATA[theliquidwave]]></dc:creator><pubDate>Mon, 08 Feb 2010 14:42:21 GMT</pubDate></item><item><title><![CDATA[Reply to std::map und erase on Mon, 08 Feb 2010 17:44:03 GMT]]></title><description><![CDATA[<p>theliquidwave schrieb:</p>
<blockquote>
<p>Zum iterieren: Folgendes Beispiel ist korrekt?</p>
</blockquote>
<p>Nein, du greifst auf den ungültigen Iterator zu. Wenn ein Element gelöscht wird, erhöhst du den Iterator nicht, also zeigt <code>it</code> immer noch auf das gleiche Element.</p>
<p>Aber noch was Allgemeines: Ich persönlich bin immer <strong>sehr</strong> vorsichtig, wenn es um manuelle Speicherverwaltung, C-Strings und ähnlichen Low-Level-Angelegenheiten geht. Ich kapsle solche Dinge meistens, um mit ihnen normal programmieren zu können. Normal heisst Wertsemantik und RAII, man muss nicht explizit freigeben oder sowas. Zwei <code>delete</code> s vor einem <code>erase()</code> sind schon etwas heikel, vor allem wenn man einige Zeit später wieder etwas erweitern möchte.</p>
<p>Zum Beispiel ist dein Code auch nicht exceptionsicher.</p>
<pre><code class="language-cpp">char *pszKey = new char[strlen(pszName) + 1];
    strcpy(pszKey, pszName);
    CBla *pBla = new CBla;
</code></pre>
<p>Wenn hier der Konstruktor von <code>CBla</code> oder der <code>new</code> -Operator eine Exception wirft, hast du ein irreversibles Memory Leak. Du sagst jetzt vielleicht, der Konstruktor wirft nichts. Aber mit grösster Wahrscheinlichkeit wirst du eben <strong>nicht</strong> an diesen Fall denken, wenn du in einem Monat die Klasse <code>CBla</code> plötzlich umgestaltest.</p>
<p>Im Weiteren kannst du deine <code>std::map</code> so nicht kopieren, ohne undefiniertes Verhalten zu riskieren. STL-Algorithmen sind auch gefährlich, weil sie von Wertsemantik ausgehen und Sequenzen umordnen können (ist bei assoziativen Containern nicht sehr relevant, aber allgemein). Zusammengefasst kannst du dir einige Probleme einhandeln, an die du gar nicht denkst. Wenn du vielleicht ein paar Mal einen Nachmittag lange wegen ungültiger Zeiger oder Memory Leaks debuggst, lernst du moderne C++-Konzepte wie RAII zu schätzen. <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>Gibt es überhaupt einen Grund, wieso du dynamische Speicherverwaltung brauchst? Ist <code>CBla</code> polymorph?</p>
<p>theliquidwave schrieb:</p>
<blockquote>
<p>Edit @ Nexus: Kann es sein, dass dein Beispiel dann fehlschlagen würde? Ich dachte das Ende der Map verändert sich, wenn ein neues Item eingefügt oder ein anderes gelöscht wird, bei deinem wird aber immer auf das gleiche Element verwiesen (beim Vergleich in der for-Schleife).</p>
</blockquote>
<p>Hm. Bei <code>std::vector</code> dürfte man das sicher nicht machen, aus dem erwähnten Grund. Ich bin mir nicht sicher, was der Standard darüber sagt, aber da andere Iteratoren in assoziativen Containern gültig bleiben, könnte das auf <code>end()</code> ebenfalls zutreffen.</p>
<p>Allerdings würde ich es nicht drauf ankommen lassen. Eigentlich ist das <code>it = map.begin(), end = map.end; it != end</code> lediglich eine blöde Angewohnheit von mir für reine Iterationsschleifen. Und auch da ist der Performancegewinn fragwürdig. Vielleicht sollte ich mir das wieder abgewöhnen, würde auch den Code um einiges schöner 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>
]]></description><link>https://www.c-plusplus.net/forum/post/1852593</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1852593</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Mon, 08 Feb 2010 17:44:03 GMT</pubDate></item></channel></rss>