2017-01-03 1 views
0

Простой std::vectorDifferent поведение наблюдается при делает стирание (итератора) на вектор и карты

std::vector<int> integers; 
integers.push_back(10); 
integers.push_back(11);  
cout << "Before: " << integers.size(); //prints 2 

Я попытался с помощью 3 различных версий кода, чтобы удалить каждый элемент один на один C++ 5.1 и C++ 14

Версия 1:

for(std::vector<int>::iterator it = integers.begin() ; it != integers.end() ;) 
{ 
    cout << "\nVal: " << *it; 
    it = integers.erase(it); 
} 

cout << "\nAfter: " << integers.size(); 

Выход: [Expected]

Before: 2 
Val: 10 
Val: 11 
After: 0 

Version 2 в C++ 14:

for(std::vector<int>::iterator it1, it = integers.begin() ; it != integers.end() ;) 
{ 
    cout << "\nVal: " << *it; 
    it1 = std::next(it); 
    integers.erase(it); 
    it = it1; 
} 

Выход: [Неожиданное]

Before: 2 
Val: 10 
After: 1 

В то время как для std::map, версия 2 работает, как ожидалось:

int main() { 
    std::map<int, int> m; 
    m.insert(make_pair(10, 11)); 
    m.insert(make_pair(12, 13)); 
    cout << "Before: " << m.size(); 

    for(std::map<int, int>::iterator it1, it = m.begin() ; it != m.end() ;) 
    { 
     cout << "\nVal: " << it->first << ", " << it->second; 
     it1 = std::next(it); 
     m.erase(it); 
     it = it1; 
    } 
    cout << "\nAfter: " << m.size(); 
    return 0; 
} 

Выходы:

Before: 2 
Val: 10, 11 
Val: 12, 13 
After: 0 

Даже это работает:

for(std::map<int, int>::iterator it1, it = m.begin() ; it != m.end() ;) 
{ 
    cout << "\nVal: " << it->first << ", " << it->second; 
    m.erase(it++); 
} 

Почему версия 2 работает на станд :: карте, но не на станд :: вектор?

+1

Где в стандарте указано, что 'map <> :: erase (it)' и 'vector <> :: erase (it)' должно проявлять такое же поведение с результирующим итератором? Единственное, что я знаю, это то, что первая версия гарантированно работает в общем виде. –

+0

'map :: erase' не поддерживает версию 1. Да, стандарт не указывает, что, но с точки зрения разработчика, можно легко ошибиться при использовании' version 2' с 'vector'. –

+0

Я просто попробовал, с 'it = m.erase (it);' и не использовать 'it1', я получаю' After: 0' –

ответ

1

Разница заключается в том, что std::vector итераторов становятся недействительными после удаления элемента в то время как для ассоциативных контейнеров (23.2.4 ассоциативного контейнера)

9 вставки и устанавливать член должны не далее ECT действительности итераторов и ссылок к контейнеру, а члены стирания должны аннулировать только итераторы и ссылки на стираемые элементы .

+0

Да, я прочитал его в разделе комментариев http://stackoverflow.com/a/263958/1465553; данные @Loki. Но я не уверен, почему так решено. Любая разумная причина для этого. –

+1

@SauravSahu В векторе элементы после стираемого элемента перемещаются влево на одну позицию. –

+0

Хорошо ... эта причина действительно имеет смысл. –

Смежные вопросы