2016-11-13 6 views
0

Я прочитал в стандарте C++ 14, что порядок элементов сохраняется при использовании erase(iterator pos) из unordered_set.Неузначает unordered_set :: erase (pos) сохранить порядок элементов?

Я пробовал следующий код с g ++ - 6.2.0 и clang-3.9 (на linux, хотя это stdlib gcc). Оба должны быть в состоянии справиться с этим с помощью C++ 14-спецификации, я думаю:

#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 
} 

Да, порядок элементов является произвольным. Здесь MSVC++ 19.00 имел 9 1 2 3 4 5 6 7 8 10. И после стирания всех четных элементов остальные элементы остаются в том же порядке 9 1 3 5 7.

С г ++ и лязгом ++, хотя, я получил совершенно плохой выход

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

, который, кажется, указывает, что порядок элементов был не сохранились между вызовами, но просто ... Я не знать.

Что происходит?

+0

Стандарт имеет более 1000 страниц текста. Говорить, что вы читаете это в стандарте, не полезно. Где в стандарте вы прочитали это? – hvd

ответ

3

Я полагаю, что этот цикл является неправильным:

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

Если Стирание выполняется тогда это аннулируется, и вы не можете увеличить его. Предположительно это вызывает вышеупомянутое поведение.

Вы должны использовать что-то вроде этого:

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

argh! Да, конечно! – towi

+0

Или вы можете просто использовать возвращаемое значение 'erase'. –

+0

@JesperJuhl только с C++ 11. –