Was gibt std::map::erase() zurück?



  • Ich habe eine Frage:

    Laut Dinkumware und der MSDN gibt map::erase den iterator auf das Element nach dem gelöschten, bzw. end() zurück, falls die map danach leer ist.

    Der GCC (und der Comeau(!)) beschweren sich aber über folgenden Code:

    #include <map>
    
    using namespace std;
    
    typedef map<int,int> mapType;
    
    int main(void)
    {
        mapType theMap;
        ++theMap[5];
        ++theMap[7];
        mapType::iterator it = theMap.begin();
        it = theMap.erase(it);
        return(0);
    }
    

    Der Fehler lautet wie folgt:

    "ComeauTest.c", line 13: error: no operator "=" matches these operands
                operand types are: std::_Rb_tree_iterator<std::pair<const int,
                          int>, std::pair<const int, int> &, std::pair<const int,
                          int> *> = void
          it = theMap.erase(it);
             ^
    
    1 error detected in the compilation of "ComeauTest.c".
    

    Also gibt deren Meinung nach map::erase void zurück...

    Das nennt sich dann standarisiert 🙄

    Felix



  • ist halt nur bei visual c++ so



  • Laut Standard hat die Methode mit einem Iterator als Übergabe als Returntype void. Somit alles korrenkt.



  • Nur bei einem sequenziellen Container gibt erase einen Iterator zurück, bei assoziativen Containern keinen Wert.



  • okay... darüber stolper ch auch gerade.

    im standard ist void erase(iterator) definiert.

    meine schleife (pseudo) in VS:

    for(map<int,int >::iterator pos=tree.begin(); pos!=tree.end(); )
    {
       if(pos->second == 1)
       {
          ...
          ++pos;
       }
       else pos = tree.erase(pos);
    }
    

    gib es da ne besser möglichkeit als dies durch

    for(map<int,int >::iterator pos=tree.begin(); pos!=tree.end(); )
    {
       if(pos->second == 1)
       {
          ...
          ++pos;
       }
       else
       {
           map<int,int >::iterator tmp = pos;
           ++pos;
           tree.erase(tmp);
       }
    }
    

    [/cpp]

    zu ersetzen?



  • Du könntest den Postfix-Inkrement nutzen:

    for(map<int,int >::iterator pos=tree.begin(); pos!=tree.end(); )
    {
       if(pos->second == 1)
       {
          ...
          ++pos;
       }
       else
           tree.erase(pos++);//pos läuft weiter und anschließend bekommt tree seine ehemalige Position zum Löschen übergeben
    }
    


  • quasi die interne kopie die bei iteratoren beim postfix++ gemacht wird, ja?



  • muffmolch schrieb:

    quasi die interne kopie die bei iteratoren beim postfix++ gemacht wird, ja?

    Genau die - der Vorteil gegenüber deiner Version ist, daß der Compiler anonyme Variablen oft besser optimieren kann (und du hast weniger zu schreiben).



  • und letzteres macht den code übersichtlicher udn weniger fehleranfällig


Anmelden zum Antworten