C++, как пройти через unordered_map
Подводя итог моей проблеме, в "unordered_map" я буду добавлять пару, имя с номером и отправлять ее в функцию. (функция не имеет значения, что она делает.) Итак, я добавлю еще одну вещь в графическую карту, но я хочу иметь возможность перейти к следующей вещи, которую я добавила в список, потому что я хочу бросить имя метки в функция следующая.
Вот код
unordered_map<string,int> graph;
unordered_map<string,int>:: iterator it;
using namespace std;
int main(){
string name;
graph.insert(pair<string,int>("Sue",4));
it=graph.begin();
name = it -> first; //name is equal to "Sue"
function(name);
graph.insert(pair<string,int>("Mark",83));
it++ // this will not work
name = it -> first; //this will not end up equaling to "Mark"
function(name);
}
дела ++it
не работает, возвращаясь --it
не работает тоже.
Так есть ли у кого-нибудь решение, как я могу пойти назад, чтобы получить name = it -> first
быть Mark
?
Примечание: (Я буду делать этот метод несколько раз, потому что он будет в цикле.)
2 ответа
За unordered_map
, не гарантируется, что элемент, вставленный после другого элемента, также будет сохранен после этого элемента. Это то, что подразумевается под неупорядоченной картой.
В этом случае вам не повезло: std::hash<std::string>
сговорился позволить "Сью" последовать за "Марком" и it++
указывает на graph.end()
а также it->first
разыменовывает это, с ошибкой памяти.
Если бы вы использовали заказанный map<string, int>
и вставьте "Сью" после "Марк" (или вы бы использовали std::greater
как map
сравнение для вашего первоначального порядка "Марк" после "Сью"), то порядок элементов, что вы ожидаете.
#include <unordered_map>
#include <map>
#include <iostream>
using namespace std;
map<string,int> graph;
map<string,int>:: iterator it;
int main()
{
string name;
graph.insert(pair<string,int>("Mark",4));
it=graph.begin();
name = it -> first; //name is equal to "Sue"
std::cout << name;
graph.insert(pair<string,int>("Sue",83));
it++ ;// this will not work
name = it -> first; //this will not end up equaling to "Mark"
std::cout << name;
}
Я думаю, это потому, что значения итератора генерируются при вызове Begin()
,
На некоторых других языках (C#), если IEnumerable
(например List
) меняется пока IEnumerator
(он же итератор) активен, Enumerator
становится недействительным и следующее IEnumerator::MoveNext()
бросит InvalidOperationException
,
см. статью MSDN по методу IEnumerator.MoveNext ()
Также эта статья о CPPReference гласит:
Если перефразирование происходит из-за вставки, все итераторы становятся недействительными. В противном случае итераторы не будут затронуты. Ссылки не являются недействительными. Перефразирование происходит только в том случае, если новое количество элементов равно или больше, чем max_load_factor()*bucket_count().