2016-11-13 3 views
0

J'ai lu dans la norme de C++ 14 que l'ordre des éléments est préservé lors de l'utilisation erase(iterator pos) de unordered_set.Est-ce que unordered_set :: erase (pos) préserve l'ordre des éléments?

J'ai essayé le code suivant avec g ++ - 6.2.0 et clang-3.9 (sur linux cependant, stdlib de ce gcc). Les deux devraient être en mesure de traiter que par les 14 spécifications C++, je pense:

#include <unordered_set> 
#include <iostream> 
using std::unordered_set; using std::cout; 

// output 
template<typename Elem, typename Comp> 
std::ostream& operator<<(std::ostream&os, const unordered_set<Elem,Comp>&data) { 
    for(auto &e : data) { os << e << ' '; } return os << '\n'; } 

int main() { 
    unordered_set<int> nums{ 1,2,3,4,5,6,7,8,9,10 }; 
    cout << nums; // MSVC: 9 1 2 3 4 5 6 7 8 10 
    for(auto it = nums.begin(); it!=nums.end(); ++it) { 
    if(*it % 2 == 0) { 
     nums.erase(it); 
    } 
    } 
    cout << nums; // MSCV: 9 1 3 5 7 
} 

Oui, l'ordre des éléments est arbitraire. Ici MSVC++ 19.00 avait 9 1 2 3 4 5 6 7 8 10. Et après avoir effacé tous les éléments pairs, les éléments restants sont toujours dans le même ordre 9 1 3 5 7.

Avec g ++ et ++ clang bien, je me suis complètement une sortie mal de

10 9 8 7 6 5 4 3 2 1 
9 8 7 6 5 4 3 2 1 

qui semble indiquer que l'ordre des éléments a été pas conservée entre les appels, mais ... Je ne sais pas connaître.

Que se passe-t-il?

+0

La norme a plus de 1000 pages de texte. Dire que vous l'avez lu dans la norme n'est pas utile. Où avez-vous lu ceci dans la norme? – hvd

Répondre

3

Je suppose que ce cycle est erroné:

for(auto it = nums.begin(); it!=nums.end(); ++it) { 
    if(*it % 2 == 0) { 
     nums.erase(it); 
    } 
} 

Si effacement est effectué alors il est invalidée et vous ne pouvez pas l'incrémenter. Vraisemblablement, il provoque le comportement susmentionné.

Vous devez utiliser quelque chose comme ceci:

for(auto it = nums.begin(); it!=nums.end();) { 
    if(*it % 2 == 0) { 
     nums.erase(it++); 
    } else { 
     ++it; 
    } 
} 
+0

argh! Oui bien sûr! – towi

+0

Ou vous pouvez simplement utiliser la valeur de retour de 'effacer'. –

+0

@JesperJuhl seulement depuis C++ 11. –