Почему multimap позволяет дублировать пары ключ-значение?

EDIT: пожалуйста заметь, я не спрашивая, почему multimap не может содержать дубликат ключи.

каково обоснование multimap, позволяющее дублировать пары ключ-значение? (не ключи)

#include <map>
#include <string>
#include <iostream>

int
main(int argc, char** argv)
{
    std::multimap<std::string, std::string> m;
    m.insert(std::make_pair("A", "B"));
    m.insert(std::make_pair("A", "B"));
    m.insert(std::make_pair("A", "C"));
    std::cout << m.size() << std::endl;
    return 0;
}

этот напечатанный 3, который несколько удивил меня, я ожидал, что multimap будет вести себя как набор пар, поэтому я ожидал 2.

интуитивно, это не согласуется с C++ std::map поведение, где insert не всегда изменяет карту (в отличие от operator[]).

есть ли смысл, или это просто произвол?

6 ответов


Multimap имеет только предикат, упорядочивающий ключи. Он не имеет метода для определения того, равны ли значения. Это значение "а" повторяющиеся значения "а"? Без второго предиката для значений невозможно сказать. Поэтому даже не имеет смысла говорить о повторяющихся значениях в multimap.

Если вам нужен контейнер, который хранит пары и обеспечивает уникальность обеих частей пары, посмотрите на boost::multi_index_container. Он очень гибкий, но принимает нагрузку аргументов в результате.


EDIT: этот ответ больше не отвечает на текущий вопрос. Я буду держать его как есть, потому что он получил upvoted много, поэтому он должен быть полезен для некоторых.

на multi на multimap означает тот факт, что то же самое ключ может возникнуть несколько раза.

стандарт не ограничивает тип, используемый в качестве значения, поэтому нельзя предположить, что operator==() определяется. Потому что нам не нужен результат вашего кода в зависимости от того, определен оператор==() или нет, он никогда не используется.

std::multimap на std::map. Как вы заметили, он ведет себя по-разному, когда один и тот же ключ вставлен несколько раз. Если вы хотите std::mapповедение, использовать std::map.

также std::multiset.

рациональный: иногда хотелось бы сохранить все старые записи для одного и того же ключа. [TBD: вставить пример здесь]

лично я почти никогда не использовать std::multimap. Если мне нужно несколько записей для одного и того же ключа, я обычно полагаюсь на std::map<std::vector<T> >.


значения могут быть дубликатами, потому что они не должны быть сопоставимы друг с другом. Контейнер не может ничего сделать со значениями, кроме их копирования. Это позволяет использовать такие типы, как multimap< int, my_class >.

Если повторяющиеся пары ключ-значение нежелательны, то используйте set< pair< T, U > > и использовать lower_bound чтобы найти первое совпадение с заданным ключом.


Как известно, multimap позволяет иметь несколько ключей. Поскольку он не накладывает никаких ограничений на сопоставимость значений, он не может проверить, не были ли значения удвоены.

Если вы хотите иметь некоторую структуру данных словаря, которая позволяет дублировать ключи, но не пары ключ-значение, вам нужно будет убедиться, что значения сопоставимы.

предположим, у нас есть какая-то игра, где есть 2D-мир полей sqaure, и вы можете поместить элементы на поля. Вы может быть multimap<Field, Item>, что позволит вам сохранить два одинаковых элемента на поле. Предметы здесь не обязательно должны быть сопоставимы.


мое рассуждение multimap основано на ключевом поиске/вставке, а не на значении. Таким образом, значение повторяющихся ключей одинаково или нет, не играет роли при вставке элементов.

23.3.2 шаблон класса multimap

1 multimap является своего рода ассоциативным контейнер, поддерживающий эквивалент ключи (возможно, содержащие несколько копии одного и того же значения ключа) и обеспечивает быстрый поиск значений из другой тип T, основанный на ключах.


"multimap" предназначен для поддержки нескольких ключей, в отличие от простого "карты". Поскольку он позволяет использовать несколько ключей, он не будет беспокоиться об их значениях, поэтому он показывает 3 элемента в вашем примере. Другое отличие в том, что нельзя иметь operator [] на multimap.