6. Метод insert контейнера std::map
race_placement.insert(move(a));
race_placement.insert(move(b));
}
7. Выходим из области видимости, и на этом все. Выводим на экран новые места гонщиков и позволяем приложению завершиться:
print(race_placement);
}
8. Компиляция и запуск программы дадут следующий результат. Сначала мы видим изначальную расстановку гонщиков, а затем новую, которую получили после изменения позиций Боузера и Донки Конга — младшего:
$ ./mapnode_key_modification Race placement:
1: Mario
2: Luigi
3: Bowser
4: Peach
5: Yoshi
6: Koopa
7: Toad
8: Donkey Kong Jr.
Race placement:
1: Mario
2: Luigi
3: Donkey Kong Jr.
4: Peach
5: Yoshi
6: Koopa
7: Toad
8: Bowser
Как это работает
В C++17 контейнер std::map
extract
. Она поставляется в двух версиях:node_type extract(const_iterator position);
node_type extract(const key_type& x);
В этом примере мы используем вторую версию, которая принимает ключ, а затем находит и извлекает соответствующий ему элемент ассоциативного массива. Первая версия функции принимает итератор, что подразумевает ее
Если мы попробуем извлечь с помощью второго метода (выполняющего поиск по ключу) элемент, которого не существует, то получим пустой экземпляр типа node_type
empty()
возвращает булево значение, которое указывает, пуст ли экземпляр node_type
. Вызов любого метода для пустого экземпляра приводит к неопределенному поведению.После извлечения узлов можно изменить их ключи с помощью метода key()
Обратите внимание: для повторного добавления узлов в ассоциативный массив нужно
insert
. Это логично, поскольку функция extract
стремится избежать создания ненужных копий и выделения памяти. Еще одно примечание: хотя мы перемещаем экземпляр типа node_type
, на самом деле никакие значения из контейнера не перемещаются.Дополнительная информация
Элементы ассоциативного массива, которые были извлечены с помощью метода extract
map
и вставить их в любой другой экземпляр типа map
или даже multimap
. Это верно и для контейнеров unordered_map
и unordered_multimap
, а также set/multiset
и, соответственно, unordered_set/unordered_multiset
.Для того чтобы можно было перемещать элементы из одной структуры ассоциативного массива или множества в другую, типы ключей, значений и средство выделения памяти должны быть идентичны. Обратите внимание: даже при совпадении этих типов мы не можем перемещать элементы из map в unordered_map
set
в unordered_set
. Применяем контейнер std::unordered_map для пользовательских типов
Использование контейнера std::unordered_map
std::map
подразумевает дополнительную степень свободы при выборе типа ключа. Контейнер std::map
требует наличия между ключами естественного порядка. Таким образом элементы можно отсортировать. Но если мы хотим, например, использовать в качестве ключа математический вектор? Мы не можем сказать, что вектор (0, 1) std::unordered_map
, поскольку мы станем различать элементы не по их величине, а по ==
, который будет проверять идентичность двух объектов. В данном разделе мы рассмотрим пример такой реализации.Как это делается
В примере мы определим простую структуру coord
coord
с числами.1. Сначала включим все необходимое, чтобы вывести на экран и использовать контейнер std::unordered_map
#include
#include
2. Далее определим собственную структуру, которую не так-то просто хешировать с помощью существующих хеш-функций:
struct coord {
int x;
int y;
};