Как бы вы сделали итератор в качестве ключа hash_map? - PullRequest
1 голос
/ 29 сентября 2011

Как бы вы сделали итератор ключом hash_map?
Как бы вы определили это в gcc, Microsoft c ++?

Е.Г.

    vector<string>::iterator i;
    hash_map<vector<string>::iterator, int> h;

или

    list<string>::iterator i;
    hash_map<list<string>::iterator, int> h;

Это дает ошибку, поскольку итераторы не предопределены как строковые, а другие типы ...

Blockquote

Ответы [ 3 ]

4 голосов
/ 29 сентября 2011

Не рекомендуется хранить итераторы вектора, чтобы использовать их в качестве ключей в ассоциативном контейнере, поскольку итераторы вектора нестабильны, то есть они становятся недействительными на insert, remove, resize, push_back и так далее (см. Правила аннулирования итераторов ).

Простой индекс гораздо безопаснее в этом отношении:

hash_map<size_t, int> h;

Вы можете преобразовать индекс в итератор просто:

size_t index = ...
std::vector<std::string> vec(...);
std::vector<std::string>::iterator i = vec.begin() + index;

И итератор обратно к индексу:

index = i - vec.begin();
2 голосов
/ 29 сентября 2011

FWIW:

использование итераторов таким способом НЕ является надежным. Итераторы становятся недействительными для определенных операций, которые действуют на контейнер. С этого момента ваши ключи hash_map станут недействительными.

Я предлагаю использовать

hash_map<string, int> h;

или

vector<string*> i;
hash_map<string*, int> h;

или даже

vector<shared_ptr<string> > i;
hash_map<shared_ptr<string>, int> h;
1 голос
/ 29 сентября 2011

Если вы знаете, что делаете (например, если итераторы взяты из неизменяемого контейнера), вы можете попытаться использовать тот факт, что &*it должен быть уникальным для каждого элемента:

typedef std::string my_container;
typedef my_container::const_iterator my_iterator;

struct IteratorHasher
{
  std::size_t operator()(const my_iterator & it) const
  {
    return hasher(&*it);
  }
private:
  std::hash<const char *> hasher;
};

Использование:

int main()
{
   std::unordered_map<my_iterator, int, IteratorHasher> mymap;

   std::string hello("hello");
   mymap[hello.begin()] = 3;
}
...