Unordered_multimap - итерация результата find() дает элементы с разным значением

Мультимап в С++, похоже, работает очень странно, мне хотелось бы знать, почему

#include <iostream>
#include <unordered_map>

using namespace std;

typedef unordered_multimap<char,int> MyMap;

int main(int argc, char **argv)
{
    MyMap map;
    map.insert(MyMap::value_type('a', 1));
    map.insert(MyMap::value_type('b', 2));
    map.insert(MyMap::value_type('c', 3));
    map.insert(MyMap::value_type('d', 4));
    map.insert(MyMap::value_type('a', 7));
    map.insert(MyMap::value_type('b', 18));

    for(auto it = map.begin(); it != map.end(); it++) {
        cout << it->first << '\t';
        cout << it->second << endl;
    }

    cout << "all values to a" << endl;
    for(auto it = map.find('a'); it != map.end(); it++) {
        cout << it->first << '\t' << it->second << endl;
    }

}

это результат:

c   3
d   4
a   1
a   7
b   2
b   18
all values to a
a   1
a   7
b   2
b   18

почему вывод все еще содержит что-либо с b в качестве ключа, когда я явно прошу "a"? Является ли это компилятором или stl-ошибкой?

Ответ 1

find, как реализовано, возвращает итератор для первого элемента, который соответствует ключу в мультимаре (как и в любой другой карте). Вероятно, вы ищете equal_range:

// Finds a range containing all elements whose key is k.
// pair<iterator, iterator> equal_range(const key_type& k)
auto its = map.equal_range('a');
for (auto it = its.first; it != its.second; ++it) {
    cout << it->first << '\t' << it->second << endl;
}

Ответ 2

Это не ошибка, это по дизайну. find возвращает итератор в один из соответствующих элементов, что и все. Вы перейдете к концу карты с помощью своей конструкции.

Вам нужно использовать multimap::equal_range, чтобы сделать то, что вам нужно.

Ответ 3

В www.cplusplus.com есть пример: Как использовать метод equal_range для получения всех элементов с одним и тем же ключом.

// unordered_multimap::equal_range
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>

typedef std::unordered_multimap<std::string,std::string> stringmap;

int main ()
{
  stringmap myumm = {
     {"orange","FL"},
     {"strawberry","LA"},
     {"strawberry","OK"},
     {"pumpkin","NH"}
  };

  std::cout << "Entries with strawberry:";
  auto range = myumm.equal_range("strawberry");
  for_each (
    range.first,
    range.second,
    [](stringmap::value_type& x){std::cout << " " << x.second;}
  );

  return 0;
}

Пожалуйста, обратитесь к ссылке: http://www.cplusplus.com/reference/unordered_map/unordered_multimap/equal_range/

Ответ 4

Казалось бы, вы получите итератор в полный "список" пар, начиная с первой пары с "a" в качестве ключа. Поэтому, когда вы повторяете до конца, вы, естественно, получите все, кроме "а". Если вы искали "c", вы, вероятно, перебирали весь "список", делая то, что вы там делаете. Возможно, вам нужно перебрать "it!= Map.end() & it- > first == 'a'", если вы хотите все a.