Dekrementieren von begin() (bidirektional)



  • Hallo,

    ich habe ein seltsames Phänomen beim Dekrementieren des begin() Iterators einer map entdeckt, und wollte mal fragen, was es damit auf sich hat.

    Folgender Code funktioniert wie erwartet unter MSVC++10, MSVC++11, g++ 4.6.1, d. h. der begin() Iterator, der anfangs auf die m[1] zeigt, zeigt nach dem Dekrementieren auf end().

    #include <map>
    #include <cassert>
    
    int main()
    {
    	std::map<int, int> m;
    	m[1] = 1;
    	m[2] = 2;
    	m[3] = 3;
    
    	std::map<int, int>::iterator it = m.begin();
    	--it;
    
    	assert(it == m.end());
    
    	return 0;
    }
    

    Entfernt man jetzt z. B. die Zeile "m[3] = 3;", so funktioniert obiges Beispiel zwar unter MSVC++ Versionen immer noch wie erwartet, bei g++ 4.6.1 bleibt der Iterator aber auch nach dem Dekrementieren auf begin().

    Ist das ein Bug?
    Oder was hat es damit auf sich?



  • Undefiniertes Verhalten. Du darfst begin() nicht dekrementieren.

    Was eine spezifische Implementierung für Eigenheiten aufweist, ist irrelevant. Sie kann sich von Version zu Version ändern, und unterscheidet sich -- wie du siehst -- bei verschiedenen Compilern. Folglich kannst du dich nicht auf ein bestimmtes Verhalten verlassen. Ist hier aber kein grosser Verlust...



  • Und wo genau kann man den Standard nachgucken, um zu sehen, dass das Dekrementieren von begin() nicht klar definiert ist?



  • Auf http://www.open-std.org/ kannst du dir die Drafts ansehen. Aber was erwartest du bei der Dekrementierung von begin() für ein Resultat? Ich sehe nicht ein, wozu man sowas tun wollte...



  • Danke!

    Weil der Iterator für einen gesuchten Term steht und end() == "Nicht Gefunden" bedeutet. (Und da --it die letzte Operation bei mir ist, soll ein Dekrementieren "Nicht Gefunden" bedeuten, falls it gleich begin() ist.)



  • Falls du rückwärts iterieren willst, wären die Methoden rbegin() und rend() etwas für dich. Aber std::map hat auch ein find() .

    Und falls du was ganz Spezielles baust, kannst du ja immer noch mit if auf begin() prüfen und in diesem Fall end() zuweisen.


Anmelden zum Antworten