<?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[erase, insert- Methoden und die Iteratoren. Verständnissproblem!]]></title><description><![CDATA[<p>Hallo,</p>
<p>schreibe mir gerade Methoden für eine eigene Liste und es fällt mir schwer, folgendes nachzuvollziehen.</p>
<p>Bsp. splice:</p>
<p>Das hier funktioniert, wie gewünscht:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{
	if(this == &amp;other) return;

	iterator beg(other.begin()), end(other.end()); 
	for( ; beg != end; ++beg)
	{
		this-&gt;insert(pos, *beg);
		other.erase(beg);
	}
}
</code></pre>
<p>Wenn ich aber nun die Iteratoren innerhalb der for-Schleife definiere, gibt es schweres Fehlverhalten.</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{
	if(this == &amp;other) return;

	for(iterator iter(other.begin()); iter != other.end(); ++ iter)
	{
		this-&gt;insert(pos, *iter);
		other.erase(iter);
	}
}
</code></pre>
<p>Ich weiss dass Iteratoren durch Insert/Erase-Operationen ungültig werden können. Aber sollte das nicht eher bei der ersten Version der Fall sein?</p>
<p>Eine weitere Frage zum Thema. In welcher Situation arbeitet man mit dem Returnwert, welcher erase() zurück liefert.<br />
Also im Falle meiner ersten Version:</p>
<pre><code class="language-cpp">beg = other.erase(beg);
</code></pre>
<p>Ich hoffe, jemand kann mir das ein bisschen näher bringen.</p>
<p>Gruss,<br />
smooth</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/220448/erase-insert-methoden-und-die-iteratoren-verständnissproblem</link><generator>RSS for Node</generator><lastBuildDate>Wed, 07 Oct 2026 03:55:38 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/220448.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 16 Aug 2008 12:09:41 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 12:19:56 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>schreibe mir gerade Methoden für eine eigene Liste und es fällt mir schwer, folgendes nachzuvollziehen.</p>
<p>Bsp. splice:</p>
<p>Das hier funktioniert, wie gewünscht:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{
	if(this == &amp;other) return;

	iterator beg(other.begin()), end(other.end()); 
	for( ; beg != end; ++beg)
	{
		this-&gt;insert(pos, *beg);
		other.erase(beg);
	}
}
</code></pre>
<p>Wenn ich aber nun die Iteratoren innerhalb der for-Schleife definiere, gibt es schweres Fehlverhalten.</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{
	if(this == &amp;other) return;

	for(iterator iter(other.begin()); iter != other.end(); ++ iter)
	{
		this-&gt;insert(pos, *iter);
		other.erase(iter);
	}
}
</code></pre>
<p>Ich weiss dass Iteratoren durch Insert/Erase-Operationen ungültig werden können. Aber sollte das nicht eher bei der ersten Version der Fall sein?</p>
<p>Eine weitere Frage zum Thema. In welcher Situation arbeitet man mit dem Returnwert, welcher erase() zurück liefert.<br />
Also im Falle meiner ersten Version:</p>
<pre><code class="language-cpp">beg = other.erase(beg);
</code></pre>
<p>Ich hoffe, jemand kann mir das ein bisschen näher bringen.</p>
<p>Gruss,<br />
smooth</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565928</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565928</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 12:19:56 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 12:18:15 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{
    if(this == &amp;other) return;

    for(iterator iter(other.begin()); iter != other.end(); ++ iter)
    {
        this-&gt;insert(pos, *beg);
        other.erase(beg);
    }
}
</code></pre>
<p>hier gibt es nirgends ein &quot;beg&quot; - das soll &quot;iter&quot; sein, oder?:</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565932</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565932</guid><dc:creator><![CDATA[Checker*amp*Murckser]]></dc:creator><pubDate>Sat, 16 Aug 2008 12:18:15 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 12:20:45 GMT]]></title><description><![CDATA[<p>Ja danke, habs verbessert!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565933</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565933</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 12:20:45 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 12:26:47 GMT]]></title><description><![CDATA[<p>warum nicht so?</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
  void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
    {
      if (this == &amp;other) return; //würd ich in nen assert packen, weil es doch schwer nach nem logikfehler aussieht...

      for(iterator iter (other.begin()), end (other.end ()); iter != end; ++iter)
        {
          insert(pos, *iter);
        }
      other.clear ();       
    }
</code></pre>
<p>oder</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
  void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
    {
      if (this == &amp;other) return; //würd ich in nen assert packen, weil es doch schwer nach nem logikfehler aussieht...

      for(iterator iter (other.begin()); ! other.empty (); ) //alternativ auch ne while-schleife - kA...
        {
          insert (pos, *iter);
          iter = other.erase (iter);
        }
    }
</code></pre>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565935</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565935</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 16 Aug 2008 12:26:47 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 12:43:13 GMT]]></title><description><![CDATA[<p>Hey,<br />
also in diesem speziellen Fall mag das klappen, aber ich benutze (u.a) auch andere Varianten von splice, bei der z.b nur ein Teil von der Zielliste entnommen wird. Oder meinst du damit, man solle generell erst die Inserts vornehmen, bevor man den Range erneut durchläuft und die erase-Ops durchführt, um Probleme zu vermeiden?!</p>
<p>Meinem Verständiss gehts aber leider noch nicht besser <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/1565939</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565939</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 12:43:13 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 13:26:54 GMT]]></title><description><![CDATA[<p>smooth_op schrieb:</p>
<blockquote>
<p>Hey,<br />
also in diesem speziellen Fall mag das klappen, aber ich benutze (u.a) auch andere Varianten von splice, bei der z.b nur ein Teil von der Zielliste entnommen wird. Oder meinst du damit, man solle generell erst die Inserts vornehmen, bevor man den Range erneut durchläuft und die erase-Ops durchführt, um Probleme zu vermeiden?!</p>
<p>Meinem Verständiss gehts aber leider noch nicht besser <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>
</blockquote>
<p>Der Sinn von splice besteht doch eher daran, dass gerade nicht kopiert wird (also kein insert/erase), sondern nur die Knoten verschoben werden. Das was du bis jetzt hast, könnte genauso mit einem vector, deque etc. funktionieren.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565953</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565953</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 16 Aug 2008 13:26:54 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 13:47:02 GMT]]></title><description><![CDATA[<p>Also die Beschreibungen zu den Methoden hab ich von <a href="http://sgi.com" rel="nofollow">sgi.com</a>.<br />
Dort heisst es zu dieser splice Methode:</p>
<blockquote>
<p>position must be a valid iterator in *this, and x must be a list that is distinct from *this. (That is, it is required that &amp;x != this.) All of the elements of x are inserted before position and removed from x. All iterators remain valid, including iterators that point to elements of x. [3] This function is constant time.</p>
</blockquote>
<p>Hatte das so verstanden, dass man mit insert/erase arbeiten kann.<br />
Was wäre eine geschicktere Alternative?<br />
Hauptsächlich interessieren mich jedoch die Fragen, die ich oben gestellt habe, weil meine Methoden selbst ja funktionieren. Jedenfalls wenn ich Version 1 benutze und mir die Iteratoren mit begin()/end() vor der for-Schleife anlege.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565960</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565960</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 13:47:02 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 14:22:37 GMT]]></title><description><![CDATA[<p>Also ich würde es IMMER so machen, dass man erst überträgt und dann löscht... Sollte so gar schneller sein...</p>
<p>Ich hab aber kein Plan von der Definition/Anwendung einer splice-Funktion - hab auch noch nie davon gehört ^^ Also halte dich da mal besser an camper ^^<br />
Aber falls ich das nicht falsch verstehe, sollst du nicht die Objekte an sich kopieren sondern einfach nur den letzten Eintrag umbiegen... Das würde auch Sinn machen - von wegen</p>
<blockquote>
<p>This function is constant time.</p>
</blockquote>
<blockquote>
<p>That is, it is required that &amp;x != this.</p>
</blockquote>
<p>also doch nen assert ()...</p>
<p>Also quasi so (ungetestet, soll dir nur verdeutlichen, wie das gemeint ist):</p>
<pre><code class="language-cpp">template &lt;class T&gt;
  bool /*ok*/ mylist &lt;T&gt;::splice (const iterator pos, mylist &lt;T&gt; &amp;other) //nothrow
    {
      assert (*this != other); //hat den vorteil, dass es beim release nicht mehr überprüft wird - aber der algorithmus an sich sollte sich ja zwischen debug und release nicht ändern ^^

      Tentry &lt;T&gt; *temp; // vll mit 0 / NULL / nullptr initialisieren, aber wird hier echt nicht gebraucht...
      try
        {
          temp = new Tentry &lt;T&gt;;
        }
        catch (std::bad_alloc) //die exception an sich brauchen wir nicht - ist ja klar, was sie uns sagen will ^^
          {
            return false;
          }

      this-&gt;last.next = other.first;
      other.first.prev = this-&gt;last.next;
      this-&gt;size += ohter.size;

      other.first = temp;
      return true;
    }
</code></pre>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1565980</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1565980</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 16 Aug 2008 14:22:37 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 15:10:59 GMT]]></title><description><![CDATA[<p>Hi (un)skilled,</p>
<p>danke, jetzt hab ich verstanden was camper meinte. Dann löse ich es am Besten über eine eigene link(mylistelem&lt;T&gt;*beg, mylistelem&lt;T&gt;*end)-Methode, welche sich um die Verzeigerung kümmert und ich in den splice-Methoden benutze.</p>
<p>Wenn nun noch jemand zu den übrigen Fragen Stellung beziehen könnte, wäre ich wunschlos glücklich <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/1566014</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566014</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 15:10:59 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 16:29:51 GMT]]></title><description><![CDATA[<p>Hmm... Stell die doch noch mal ^^</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566045</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566045</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 16 Aug 2008 16:29:51 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 16:47:13 GMT]]></title><description><![CDATA[<p>Hehe okay.</p>
<p>Wieso iteriert folgendes korrekt:</p>
<pre><code class="language-cpp">iterator beg(other.begin()), end(other.end());
    for( ; beg != end; ++beg) {...}
</code></pre>
<p>und dies hier nicht:</p>
<pre><code class="language-cpp">for(iterator iter(other.begin()); iter != other.end(); ++ iter) {...}
</code></pre>
<p>Und wenn es mit den ausgeführten insert/erase Operationen zusammen hängt, wieso mache ich mir die Iteratoren dann mit der ersten Version nicht kaputt??</p>
<p>Dann interessiert mich noch, wann man bei einem erase-Aufruf den Return-Wert benutzt und wann nicht. Du hast das in deinem ersten Bsp. auch verwendet.<br />
Macht man das vlt, wenn nicht sowieso mit ++iter in der Schleife weitergeschaltet wird?!</p>
<p>Um mal von dem splice wegzukommen, das Problem taucht auch bei vielen anderen Operationen auf.<br />
Beispielsweise remove:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::remove( T const &amp;val)
{
	//for(iterator iter(this-&gt;begin()); iter != this-&gt;end(); ++iter)
	//	if(*iter == val) this-&gt;erase(iter);

	iterator beg(this-&gt;begin()), end(this-&gt;end()); 
	for( ; beg != end; ++beg)
	{
		if(*beg == val) this-&gt;erase(beg);
	}
}
</code></pre>
<p>Hier ist die alte, fehlerhafte Lösung auskommentiert.</p>
<p>Wenn was nicht verständlich ist, einfach fragen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566052</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566052</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 16:47:13 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 17:16:24 GMT]]></title><description><![CDATA[<p>smooth_op schrieb:</p>
<blockquote>
<p>Dann interessiert mich noch, wann man bei einem erase-Aufruf den Return-Wert benutzt und wann nicht. Du hast das in deinem ersten Bsp. auch verwendet.<br />
Macht man das vlt, wenn nicht sowieso mit ++iter in der Schleife weitergeschaltet wird?!</p>
</blockquote>
<p>naja... Es sieht ja so aus:</p>
<pre><code>iter
    |
    v
.---------.
| element |
| next ------&gt;  &lt;element, next, ...&gt;
| ...     |
'---------'
</code></pre>
<p>du löschst das element (mit erase) und willst DANACH noch den zeiger next haben...</p>
<pre><code>iter
    |
    v
???????????
???????????
???????????  [kein zeiger mehr da] &lt;element, next, ...&gt;
???????????
???????????
</code></pre>
<p>Das kann niemals gut gehen...</p>
<p>Wenn du erase nutzt, dann darfst du ++ nicht verwenden und MUSST den rückgabewert nutzen... Wenn du beides nimmst, hast du logischerweise nur jedes zweite element gelöscht (#1 gelöscht, iter wird auf neues #1 gesetzt (das alte #2) und dann um eins erhöht -&gt; (altes) #3)</p>
<p>und ++ macht ja nichts anderes, als next aufzurufen... und anscheind optimiert der compiler bei deiner einen variante anders als bei der anderen... außerdem bleibt noch immer die ausrede, dass es undefiniertes verhalten hervorruft, ungültige zeiger (und damit auch iteratoren) zu nutzen...</p>
<p>Um noch mal zu dem zweiten bildchen zu kommen:<br />
du hast also keine chance mehr, nach dem erase an das nächste element zu kommen (ok, das ist falsch, das geht noch über das vorige (vom gelöschten aus gesehen)prev-&gt;next - aber nicht all zu bequem und performant ^^)... deshalb gibt dir erase das nächste element wieder aus bzw einen iterator auf das nächste element...</p>
<p>ok?</p>
<p>bb</p>
<p>edit:<br />
zu der fkt an sich noch mal:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
  bool /*ok*/ mylist&lt;T&gt;::remove (T const &amp;val) //nothrow - kommt aber nat darauf an, ob erase ne exception werfen darf bzw könnte
    {
      for(iterator iter (this-&gt;begin()), end (this-&gt;end()); iter != end; ++iter)
        {
          if (*iter == val)
            {
              erase (iter); //hier brauchen wir den returnwert mal nicht
              return true;
            }
        }
      return false;
    }
</code></pre>
<p>je nach geschmack kann man das auch mit <code>if (*iter != val) continue;</code> lösen... und darunter dann das erase aufrufen...</p>
<p>btw fällt mir da gerade ma wieder ne frage ein:</p>
<pre><code class="language-cpp">erase (iter); //hier brauchen wir den returnwert mal nicht
//castet man bei so was eigtl noch auf void? also so was:
(void)erase (iter);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1566067</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566067</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 16 Aug 2008 17:16:24 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 17:48:58 GMT]]></title><description><![CDATA[<p>Nice Pics <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>Also ist es deiner Meinung nach nur Zufall, das meine erase Varianten korrekt funktionieren, weil undefiniert? Das macht mich jetzt fertig.<br />
Deine remove-Methode kommt meiner nicht ganz gleich, weil ich alle Vorkommen &quot;value&quot; löschen möchte.<br />
Ich habs mal versucht zu übertragen, aber damit läuft er nicht mehr durch meine Tests.</p>
<pre><code class="language-cpp">iterator beg(this-&gt;begin()), end(this-&gt;end()); 
	while(beg != end)
	{
		if(*beg == val) beg = this-&gt;erase(beg);
		else
			++beg;
	}
</code></pre>
<p>Zu deiner Frage. Glaube nicht das ein cast notwendig ist, habs in so einem Fall noch nie gesehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566091</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566091</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sat, 16 Aug 2008 17:48:58 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sat, 16 Aug 2008 18:23:03 GMT]]></title><description><![CDATA[<blockquote>
<p>Zu deiner Frage. Glaube nicht das ein cast notwendig ist, habs in so einem Fall noch nie gesehen</p>
</blockquote>
<p>Nötig ist er auch nicht... Aber &quot;damals&quot; war das mal in ^^</p>
<pre><code class="language-cpp">iterator iter (begin ());
while (iter != end ()) //die funktion aufrufen
  {
    if (*iter == val) //ich würd das umdrehen - fände das logischer ^^ also if (a != b) ++a else erase ()
      iter = erase (iter);
    else
      ++iter;
  }
</code></pre>
<p>warum schreibst du statt iter (für iterator) immer beg? beg stimmt genau einmal - ganz am anfang...<br />
Auch das <code>this-&gt;</code> jedes mal nervt eher als alles andere ^^</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566111</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566111</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sat, 16 Aug 2008 18:23:03 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 14:24:03 GMT]]></title><description><![CDATA[<p>Ich benutze beg, genauso wie first, weil ich verdeutlichen möchte, dass es sich um den Anfang eines definierten Range handelt. Dass er das nach einmaligem inkrementieren nicht mehr ist, stört mich jetzt nicht wirklich. Btw. arbeitet die cplusplus-Reference auch mit diesen Begriffen.<br />
Wegen dem this werde ich aber in Zukunft Rücksicht auf dich nehmen <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>Zu meiner Remove. Ob jetzt so herum logischer oder nicht, er läuft nicht mehr durch und wirft eine out_of_range exceptions (* on bad iterator). Wieso?</p>
<p>Hier noch ein Bsp, was eigentlich <strong>nicht</strong> klappen dürfte, es aber dennoch tut, obwohl ich den iterator first mit der erase-Methode lösche und first nicht aktualisiere?!</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
typename mylist&lt;T&gt;::iterator mylist&lt;T&gt;::erase(iterator first, iterator last)
{
	if(!head_ || !first.current_) return iterator();

	iterator iter; // Tmp-Iter fuer Return
	for( ; first != last; ++first) iter = erase(first);		

	return iter; 
}
</code></pre>
<p>Wenn ich sie nun umschreibe, gibts eine endlos-Schleife!</p>
<pre><code class="language-cpp">typename mylist&lt;T&gt;::iterator mylist&lt;T&gt;::erase(iterator first, iterator last)
{
	if(!head_ || !first.current_) return iterator();

	while(first != last) first = erase(first);

	return first; 
}
</code></pre>
<p>Ich weiss nicht, was ich falsch mache. Da es hier sicher ein paar STL-Fans gibt, würd ich mich über einer Erklärung freuen.</p>
<p>Viele Grüsse,<br />
smooth</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566420</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566420</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sun, 17 Aug 2008 14:24:03 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 15:35:56 GMT]]></title><description><![CDATA[<p>smooth_op schrieb:</p>
<blockquote>
<p>Ich weiss nicht, was ich falsch mache. Da es hier sicher ein paar STL-Fans gibt, würd ich mich über einer Erklärung freuen.</p>
</blockquote>
<p>Ich nehme an, dass du durchaus weißt, was falsch ist. Dass das erste Beispiel bei dir möglicherweise &quot;funktioniert&quot;, ist letztlich unerheblich. Die erste Varianten resultiert in undefiniertem Verhalten - und undefiniert heißt eben nicht &quot;funktioniert nicht&quot;, sondern dass keine bestimmte Aussage in irgendeiner Hinsicht möglich ist.</p>
<p>Das Problem mit dem zweiten Beispiel liegt woanders - ich würde vermuten, dass irgendeine elementare Funktion bei dir fehlerhaft implementiert ist. Der if-Teil darin ergibt übrigens nicht viel Sinn.<br />
Grundsätzlich kann man bzgl. der Parameter voraussetzen, dass<br />
[first,last) eine Sequenz ist, und sowohl first als auch last in [begin(),this-&gt;end()] liegen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566450</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566450</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 17 Aug 2008 15:35:56 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 15:40:06 GMT]]></title><description><![CDATA[<p>Poste doch einfach mal, was erase genau macht... wenn deine liste während des vorgangs rumkopieren darf, dann ist es z.bsp. klar, dass <code>end</code> dann nicht mehr mit <code>end ()</code> übereinstimmt...</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566456</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566456</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sun, 17 Aug 2008 15:40:06 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 16:25:58 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a><br />
Ja, dank unskilled ist mir klar, wieso ich mir die Position merken muss. Aber es leuchtet nicht ein, wieso die &quot;verbesserten&quot; Varianten noch nicht wollen.<br />
Wg den if-Abfragen: Wenn es keinen head_ gibt, kann es auch nichts zu löschen geben. Wozu sollte man dann irgendwas auswerten, temp. Iteratoren anlegen etc., wenn man die Funktion doch sofort wieder verlassen kann? Whatever, das sind Feinheiten und die interessieren mich momentan eher wenig.</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16305">@unskilled</a><br />
erase sollst du kriegen, mmn korrekt. Aber was weiss ich schon <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>
<pre><code class="language-cpp">template &lt;typename T&gt;
typename mylist&lt;T&gt;::iterator mylist&lt;T&gt;::erase(iterator pos)
{
	if(!pos.current_ || !head_) return iterator(); 

	mylistElem&lt;T&gt; *elem(pos.current_), *nextelem(pos.next_);

	if(elem == head_) head_ = head_-&gt;next_; if(!head_) tail_ = head_;
	if(elem == tail_) tail_ = tail_-&gt;prev_;	if(!tail_) head_ = tail_;

	elem-&gt;unlink_(); // hier wird ausgehängt (Verzeigerung aktualisieren)
	delete elem;
	elem = 0;

	--size_;

	if(!nextelem) 
		return end();
	else
	{
		iterator iter;
		iter.current_ = nextelem;
		iter.prev_ = nextelem-&gt;prev_;
		iter.next_ = nextelem-&gt;next_;
		return iter;
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1566489</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566489</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sun, 17 Aug 2008 16:25:58 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 16:36:01 GMT]]></title><description><![CDATA[<p>Wie sieht der Vergleichsoperator des Iterators aus und wie die end-Funktion der Liste?<br />
Nachdem ich die erase-Funktion gesehen habe, kann ich bereits ahnen, was mit dem end()-iterator passiert, wenn das letzte Element einer Liste gelöschte wird.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566493</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566493</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 17 Aug 2008 16:36:01 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 16:57:58 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;typename T&gt;
bool mylist&lt;T&gt;::iterator::operator==(iterator const &amp;other) const throw()
{
	return (prev_ == other.prev_ &amp;&amp; current_ == other.current_
	&amp;&amp; next_ == other.next_);
}
</code></pre>
<pre><code class="language-cpp">template &lt;typename T&gt;
typename mylist&lt;T&gt;::iterator mylist&lt;T&gt;::end() throw()
{
	iterator iter;
	iter.current_ = iter.next_ = 0;
	iter.prev_ = tail_;
	return iter;
}
</code></pre>
<p>So und nu lass mich an deinen Vermutungen teilhaben <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/1566514</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566514</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sun, 17 Aug 2008 16:57:58 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 17:21:27 GMT]]></title><description><![CDATA[<p>List-Iteratoren sind stabil bei allen List-Operationen, die die Elemente, auf die diese Iteratoren verweisen, nicht verändern. Insbesondere gilt für den End-Iterator, dass dieser sich während der gesamten Lebensdauer eines List-Objekts nicht verändert (außer evtl. bei swap). Diese Eigenschaft hat dein end-Iterator aber nicht. Betrachte</p>
<pre><code class="language-cpp">list.erase(list.begin(),list.end())
</code></pre>
<p>Der Iterator, der nach dem Löschen des letzten Elements zurückgegeben wird, ist nicht glich dem ursprünglichen Funktionsargument.</p>
<p>Schlimmer noch, offenbar duplizieren deine Iteratoren die Link-Information der Knoten, auf die sie zeigen. Das darf du nicht tun, da sich diese Informationen ändern können, ohne dass der Iterator das mitbekommt.</p>
<pre><code class="language-cpp">MyList&lt;int&gt; list;
MyList&lt;int&gt;::iterator end = list.end();
list.push_back(1);
--end; // sollte jetzt auf das eingefügte Element zeigen
</code></pre>
<p>Spätestens an dieser Stelle wird der Vorteil von Ringlisten mit dummy-Element deutlich, mit diesen erreicht man das Verhalten auf triviale Weise.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566525</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566525</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 17 Aug 2008 17:21:27 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 18:05:46 GMT]]></title><description><![CDATA[<p>Danke für die Erläuterung.<br />
Ich fürchte jedoch, ich kann dir nicht ganz folgen. Wenn das letzte Element der Liste gelöscht wird, gibts end() als Return. Da end() immer gleich aussieht, sollte das doch passen.<br />
Die Sache ist, ich habe hier einen 2600-Zeilen langen Testtreiber, der größtenteils vom Prof stammt und wirklich jedes Detail der Liste checked.<br />
So etwas markantes müsste also eigentlich auffallen.<br />
An welcher Stelle würdest du anpacken?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566545</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566545</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sun, 17 Aug 2008 18:05:46 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 18:20:45 GMT]]></title><description><![CDATA[<p>Ich hab mittlerweile übringes meine splice gepimped.<br />
So sollte es im Sinne der STL sein, oder?</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::splice(iterator pos, mylist&lt;T&gt; &amp;other)
{

	if(this == &amp;other) return;

	mylistElem&lt;T&gt; *frst(other.head_), *lst(other.tail_);
	frst-&gt;unlink_(lst);    // hier wird frst bis einschliesslich lst ausgehaengt

	if(!head_) // Liste noch leer
	{
		head_ = frst; head_-&gt;prev_ = 0;
		tail_ = lst;	tail_-&gt;next_ = 0;	
	}
	else if(pos.current_) // Innerhalb der Liste
	{
		pos.current_-&gt;link_(frst, lst, false); // vor!! pos.current_ plazieren
	}
	else // am Ende anheangen
	{
		tail_-&gt;link_(frst, lst, true); // hinter!! aktuellem tail_ plazieren
	}

	if(!frst-&gt;prev_) head_ = frst; head_-&gt;prev_ = 0;
	if(!lst-&gt;next_) tail_ = lst; tail_-&gt;next_ = 0;

	size_ += other.size_;
	other.head_ = other.tail_ =  0;
	other.size_ = 0;

}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1566554</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566554</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Sun, 17 Aug 2008 18:20:45 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 19:02:34 GMT]]></title><description><![CDATA[<p>smooth_op schrieb:</p>
<blockquote>
<p>Danke für die Erläuterung.<br />
Ich fürchte jedoch, ich kann dir nicht ganz folgen. Wenn das letzte Element der Liste gelöscht wird, gibts end() als Return. Da end() immer gleich aussieht, sollte das doch passen.</p>
</blockquote>
<p>schau dir einfach einmal</p>
<pre><code class="language-cpp">MyList&lt;int&gt; list;
MyList&lt;int&gt;::iterator end1 = list.end();
list.push_back(1);
MyList&lt;int&gt;::iterator end2 = list.end();
assert(end1==end2);
--end1;
assert(list.erase(end1)==end2);
</code></pre>
<p>an.</p>
<blockquote>
<p>Die Sache ist, ich habe hier einen 2600-Zeilen langen Testtreiber, der größtenteils vom Prof stammt und wirklich jedes Detail der Liste checked.<br />
So etwas markantes müsste also eigentlich auffallen.<br />
An welcher Stelle würdest du anpacken?</p>
</blockquote>
<p>Der bloße Zeilenumfang sagt wenig aus, worauf es ankommt, ist doch, was getestet wird. Einige Dinge solltest du auch selbst testen - zum Beispiel die Gültigkeit von Argumenten zumindest beim Debuging. Den Anwender freut es, wenn er die fehlerhafte Anwendung deiner Liste mit einer entsprechenden Fehlermeldung quittiert bekommt an Stelle von merkwürdigem Verhalten.<br />
Das würde auch in deinem Fall helfen. Ich bin einigermaßen sicher, dass das Inkrementieren eines end-Iterators einfach übergangen wird, anstatt mit Programmabbruch quittiert zu werden - obwohl das bei dieser Implementation trivial zu erkennen ist. Dann würde dein ursprünglicher Code keine Endlosschleife, sondern einen Programmabbruch produzieren. Weil dein end-Iterator nicht stabil ist, kann die Abbruch-Bedingung first==last in der erase-Funktion niemals erfüllt sein, wenn das Ende der zu löschenden Sequenz mit dem Ende des Containers übereinstimmt. Bei der Version, die eigentlich undefiniert ist, &quot;funktioniert&quot; es dagegen aus dem Grunde, dass das Inkrementieren auf noch unveränderten gelöschten Daten (also den alten Link-Informationen) beruht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566555</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566555</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 17 Aug 2008 19:02:34 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Sun, 17 Aug 2008 23:16:51 GMT]]></title><description><![CDATA[<p>warum hältst du so an deinem</p>
<pre><code class="language-cpp">if(this == &amp;other) return;
</code></pre>
<p>fest und nimmst nicht die</p>
<pre><code class="language-cpp">assert (this != &amp;other);
</code></pre>
<p>-Variante?</p>
<p>Ich seh da nur Vorteile drin - aber kA...</p>
<p>bb</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1566660</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566660</guid><dc:creator><![CDATA[unskilled]]></dc:creator><pubDate>Sun, 17 Aug 2008 23:16:51 GMT</pubDate></item><item><title><![CDATA[Reply to erase, insert- Methoden und die Iteratoren. Verständnissproblem! on Mon, 18 Aug 2008 12:42:54 GMT]]></title><description><![CDATA[<p>Hallo die Herren,</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/16305">@unskilled</a><br />
weil ich momentan noch an ganz anderen Fronten kämpfe. Wenn alles so passt, wie es soll, kann ich mich um solche Feinheiten kümmern. Wurde aber zur Kenntniss genommen <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><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/6642">@camper</a><br />
Du hast das alles schon sehr richtig analysiert. In deinem Beispiel zeigt bei mir vom ersten end()-Iterator alles auf 0, weil es noch keine Elemente gibt. Der zweite end()-Iterator besitzt einen Vorgänger, nämlich das bei tail_ neu eingefügte-Element, daher sind sie ungleich.<br />
Auch mit der Tatsache dass das letzte Element einer Sequenz Probleme bereitet, liegst du richtig. Habe folgendes bei meiner remove-Methode versucht:</p>
<p>remove...</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
void mylist&lt;T&gt;::remove( T const &amp;val)
{
	iterator beg(begin());
	while(beg != end())
	{
		if(*beg == val) beg = erase(beg);
		else
			++beg;
	}
}
</code></pre>
<p>Test läuft durch:</p>
<pre><code class="language-cpp">mylist&lt;string&gt; v;
v.push_back(&quot;Januar&quot;); v.push_back(&quot;Februar&quot;); v.push_back(&quot;Maerz&quot;);
//v.push_back(&quot;Januar&quot;);
v.remove(&quot;Januar&quot;);
mylist&lt;string&gt;::iterator iter(v.begin());
for( ; iter != v.end(); ++iter)
	{
          if(*iter == &quot;Januar&quot;) break;
	}
assert(iter == v.end());
}
</code></pre>
<p>Wenn man das letzte Januar, welches dem Suchwort entspricht, wieder einkommentiert, kracht es.</p>
<p>Ich bin mir leider immer noch nicht sicher, an welcher Stelle ich anpacken soll?<br />
Ist es das end(), welches erase im Falle des letzten Elements zurück gibt, oder das Inkrementieren der Iteratoren, oder doch was ganz anderes?!<br />
Hab auch eine Debug-Session hinter mir, aber ich werd einfach nicht schlau daraus <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>
]]></description><link>https://www.c-plusplus.net/forum/post/1566915</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1566915</guid><dc:creator><![CDATA[smooth_op]]></dc:creator><pubDate>Mon, 18 Aug 2008 12:42:54 GMT</pubDate></item></channel></rss>