Подтвердить что ты не робот

Почему 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.

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

Есть ли обоснование позади, или это просто произвольно?

4b9b3361

Ответ 1

Multimap имеет только предикат, упорядочивающий ключи. У него нет способа определить, равны ли значения. Является ли значение "А" дубликатом значения "а"? Без второго предиката для значений нет никакой информации. Таким образом, даже не имеет смысла говорить о повторяющихся значениях в мультимадре.

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

Ответ 2

РЕДАКТИРОВАТЬ: этот ответ больше не отвечает на текущий вопрос. Я сохраню его, потому что он получил много преимуществ, поэтому он должен быть полезен для некоторых.

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

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

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

Существует также std::multiset.

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

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

23.3.2 Многомерный шаблон шаблона

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