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().

Другие вопросы по тегам