Именованные требования C++: UnorderedAssociativeContainer (начиная с C++11)
Неупорядоченные ассоциативные контейнеры — это контейнеры, обеспечивающие быстрый поиск объектов по ключам. В худшем случае сложность линейная, но в среднем большинство операций выполняется гораздо быстрее.
Неупорядоченные ассоциативные контейнеры параметризуются Key; Hash — объектом-функцией хеширования, которая используется как хеш-функция для Key; и Pred — объектом-функцией бинарного предиката, определяющим эквивалентность между Keys. std::unordered_map и std::unordered_multimap также имеют тип отображаемого значения T, связанный с Key.
Если согласно Pred два Keys равны, Hash должен возвращать одинаковое значение для обоих ключей.
| Если существуют и обозначают типы и | (начиная с C++20) |
std::unordered_map и std::unordered_set могут содержать не более одного элемента с заданным ключом, тогда как std::unordered_multiset и std::unordered_multimap могут содержать несколько элементов с одним и тем же ключом (которые при итерации всегда должны идти рядом).
Для std::unordered_set и std::unordered_multiset тип значения совпадает с типом ключа, а iterator и const_iterator являются константными итераторами. Для std::unordered_map и std::unordered_multimap тип значения — std::pair<constKey,T>.
Элементы неупорядоченного ассоциативного контейнера организованы по корзинам; ключи с одинаковым хешем попадут в одну и ту же корзину. При увеличении размера контейнера количество корзин увеличивается, чтобы среднее число элементов в каждой корзине не превышало определённое значение.
Перехеширование делает итераторы недействительными и может привести к перераспределению элементов по другим корзинам, но не делает недействительными ссылки на элементы.
Неупорядоченные ассоциативные контейнеры соответствуют требованиям контейнера с поддержкой аллокатора. Для std::unordered_map и std::unordered_multimap требования value_type из контейнера с поддержкой аллокатора применяются к key_type и mapped_type (но не к value_type).
Требования
Условные обозначения |
|
X | Класс неупорядоченного ассоциативного контейнера |
a | Значение типа X |
a2 | Значение типа, совместимого с узлами типа X |
b | Значение типа X или const X |
a_uniq | Значение типа X, если X поддерживает уникальные ключи |
a_eq | Значение типа X, если X поддерживает эквивалентные ключи |
a_tran | Значение типа X или constX, если квалифицированные идентификаторы X::key_equal::is_transparent и X::hasher::is_transparent допустимы и обозначают типы |
i, j | Входные итераторы, указывающие на value_type |
[i, j) | Допустимый диапазон |
rg (начиная с C++23) | Значение типа R, моделирующего container-compatible-range<value_type> |
p, q2 | Допустимые константные итераторы к a |
q, q1 | Допустимые разыменовываемые константные итераторы к a |
r | Допустимый разыменовываемый итератор к a |
[q1, q2) | Допустимый диапазон в a |
il | Значение типа std::initializer_list<value_type> |
t | Значение типа X::value_type |
k | Значение типа key_type |
hf | Значение типа hasher или consthasher |
eq | Значение типа key_equal или constkey_equal |
ke | Значение, для которого
где |
kx (начиная с C++23) | Значение, для которого
где |
n | Значение типа size_type |
z | Значение типа float |
nh (начиная с C++17) | R-значение типа X::node_type |
Типы-члены
| Имя | Тип | Требования | Примечания |
|---|---|---|---|
X::key_type |
Key | ||
X::mapped_type |
T |
Только для std::unordered_map и std::unordered_multimap | |
X::value_type |
Key |
Только для std::unordered_set и std::unordered_multiset. Удаляемый в X | |
| std::pair<constKey,T> |
Только для std::unordered_map и std::unordered_multimap. Удаляемый в X | ||
X::hasher |
Hash | Хеширование | |
X::key_equal |
Pred |
Копируемо-конструируемый; бинарный предикат, принимающий два аргумента типа Key и задающий отношение эквивалентности | |
X::local_iterator | LegacyIterator | Категория и типы совпадают с X::iterator | Может использоваться для итерации по одной корзине, но не между корзинами |
X::const_local_iterator | LegacyIterator | Категория и типы совпадают с X::const_iterator |
|
X::node_type (начиная с C++17) | Специализация шаблона класса node-handle | Открытые вложенные типы совпадают с соответствующими типами в X |
Функции-члены и операторы
| Выражение | Результат | Предусловия | Эффекты | Возвращает | Сложность |
|---|---|---|---|---|---|
X(n, hf, eq) | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и eq в качестве предиката равенства ключей | O(n) |
|||
X(n, hf) |
key_equal является DefaultConstructible | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и key_equal() в качестве предиката равенства ключей | O(n) |
||
X(n) |
hasher и key_equal являются DefaultConstructible | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей | O(n) |
||
X a = X();X a; |
hasher и key_equal являются DefaultConstructible | Конструирует пустой контейнер с неопределенным количеством корзин, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей | Константная | ||
X(i, j, n, hf, eq) |
value_type является EmplaceConstructible в X из *i | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и eq в качестве предиката равенства ключей, и вставляет в него элементы из [i, j) | В среднем O(N) (N — это std::distance(i, j)), в худшем случае O(N2) |
||
X(i, j, n, hf) |
key_equal является DefaultConstructible. value_type является EmplaceConstructible в X из *i | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из [i, j) | В среднем O(N) (N — это std::distance(i, j)), в худшем случае O(N2) |
||
X(i, j, n) |
hasher и key_equal являются DefaultConstructible. value_type является EmplaceConstructible в X из *i | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из [i, j) | В среднем O(N) (N — это std::distance(i, j)), в худшем случае O(N2) |
||
X(i, j) |
hasher и key_equal являются DefaultConstructible. value_type является EmplaceConstructible в X из *i | Конструирует пустой контейнер с неопределенным количеством корзин, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из [i, j) | В среднем O(N) (N — это std::distance(i, j)), в худшем случае O(N2) |
||
X(std::from_range,rg, n, hf, eq)(начиная с C++23) |
value_type является EmplaceConstructible в X из *ranges::begin(rg) | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и eq в качестве предиката равенства ключей, и вставляет в него элементы из rg | В среднем O(N) (N — это ranges::distance(rg)), в худшем случае O(N2) |
||
X(std::from_range,rg, n, hf)(начиная с C++23) |
key_equal является DefaultConstructible. value_type является EmplaceConstructible в X из *ranges::begin(rg) | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hf в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из rg | В среднем O(N) (N — это ranges::distance(rg)), в худшем случае O(N2) |
||
X(std::from_range,rg, n)(начиная с C++23) |
hasher и key_equal являются DefaultConstructible. value_type является EmplaceConstructible в X из *ranges::begin(rg) | Конструирует пустой контейнер по меньшей мере с n корзинами, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из rg | В среднем O(N) (N — это ranges::distance(rg)), в худшем случае O(N2) |
||
X(std::from_range,rg)(начиная с C++23) |
hasher и key_equal являются DefaultConstructible. value_type является EmplaceConstructible в X из *ranges::begin(rg) | Конструирует пустой контейнер с неопределенным количеством корзин, используя hasher() в качестве функции хеширования и key_equal() в качестве предиката равенства ключей, и вставляет в него элементы из rg | В среднем O(N) (N — это ranges::distance(rg)), в худшем случае O(N2) |
||
X(il) |
X(il.begin(), il.end()) | ||||
X(il, n) |
X(il.begin(), il.end(), n) | ||||
X(il, n, hf) |
X(il.begin(), il.end(), n, hf) | ||||
X(il, n, hf, eq) |
X(il.begin(), il.end(), n, hf, eq) | ||||
X(b) | Контейнер; копирует функцию хеширования, предикат и максимальный коэффициент заполнения | В среднем линейная от b.size(), в худшем случае O(N2) |
|||
a = b |
X& | Контейнер; копирует функцию хеширования, предикат и максимальный коэффициент заполнения | В среднем линейная от b.size(), в худшем случае O(N2) |
||
a = il |
X& |
value_type является CopyInsertable в X и CopyAssignable | Присваивает диапазон [il.begin(), il.end()) в a. Все существующие элементы a либо перезаписываются (присваиванием), либо уничтожаются | В среднем линейная от il.size(), в худшем случае O(N2) |
|
b.hash_function() |
hasher | Функция хеширования b | Константная | ||
b.key_eq() |
key_equal | Предикат равенства ключей b | Константная | ||
a_uniq.emplace(args) | std::pair< iterator, bool> |
value_type является EmplaceConstructible в X из args | Вставляет объект value_type t, сконструированный с помощью std::forward<Args>(args)..., тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t | Компонент bool возвращаемой пары равен true тогда и только тогда, когда произошла вставка, а компонент-итератор пары указывает на элемент с ключом, эквивалентным ключу t | В среднем O(1), в худшем случае O(a_uniq.size()) |
a_eq.emplace(args) |
iterator |
value_type является EmplaceConstructible в X из args | Вставляет объект value_type t, сконструированный с помощью std::forward<Args>(args)... | Итератор, указывающий на вставленный элемент | В среднем O(1), в худшем случае O(a_eq.size()) |
a.emplace_hint(p, args) |
iterator |
value_type является EmplaceConstructible в X из args |
a.emplace(std::forward<Args>(args)...) | Итератор, указывающий на элемент с ключом, эквивалентным новому вставленному элементу. const_iterator p является подсказкой, указывающей, откуда должен начинаться поиск. Реализациям разрешено игнорировать подсказку | В среднем O(1), в худшем случае O(a.size()) |
a_uniq.insert(t) | std::pair< iterator, bool> | Если t является rvalue-ссылкой без сохранения константности, value_type является MoveInsertable в X; в противном случае value_type является CopyInsertable в X | Вставляет t тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным ключу t | Компонент bool возвращаемой пары указывает, произошла ли вставка, а компонент iterator указывает на элемент с ключом, эквивалентным ключу t | В среднем O(1), в худшем случае O(a_uniq.size()) |
a_eq.insert(t) |
iterator | Если t является rvalue-ссылкой без сохранения константности, value_type является MoveInsertable в X; в противном случае value_type является CopyInsertable в X | Вставляет t | Итератор, указывающий на вставленный элемент | В среднем O(1), в худшем случае O(a_eq.size()) |
a.insert(p, t) |
iterator | Если t является rvalue-ссылкой без сохранения константности, value_type является MoveInsertable в X; в противном случае value_type является CopyInsertable в X |
a.insert(t). Итератор p является подсказкой, указывающей, откуда должен начинаться поиск. Реализациям разрешено игнорировать подсказку | Итератор, указывающий на элемент с ключом, эквивалентным ключу t | В среднем O(1), в худшем случае O(a.size()) |
a.insert(i, j) | void |
value_type является EmplaceConstructible в X из *i. Ни i, ни j не являются итераторами в a |
a.insert(t) для каждого элемента в[i, j) | В среднем O(N), где N — это std::distance(i, j), в худшем случае O(N·(a.size() + 1)) |
|
a.insert_range(rg)(начиная с C++23) | void |
value_type является EmplaceConstructible в X из *ranges::begin(rg). rg и a не перекрываются |
a.insert(t) для каждого элемента t в rg | В среднем O(N), где N — это ranges::distance(rg), в худшем случае O(N·(a.size() + 1)) |
|
a.insert(il) |
a.insert(il.begin(), il.end()) | ||||
a_uniq.insert(nh)(начиная с C++17) |
insert_return_type |
nh пуст или
| Если nh пуст, не выполняет никаких действий. В противном случае вставляет элемент, которым владеет nh, тогда и только тогда, когда в контейнере нет элемента с ключом, эквивалентным nh.key(). Гарантии: Если nh пуст, inserted равен false, position равен end(), а node пуст. В противном случае, если вставка произошла, inserted равен true, position указывает на вставленный элемент, а node пуст; если вставка не удалась, inserted равен false, node имеет предыдущее значение nh, а position указывает на элемент с ключом, эквивалентным nh.key() | В среднем O(1), в худшем случае O(a_uniq.size()) |
|
a_eq.insert(nh)(начиная с C++17) |
iterator |
nh пуст или
| Если nh пуст, не выполняет никаких действий и возвращает a_eq.end(). В противном случае вставляет элемент, которым владеет nh, и возвращает итератор, указывающий на вставленный элемент. Гарантии: nh пуст | В среднем O(1), в худшем случае O(a_eq.size()) |
|
a.insert(q, nh)(начиная с C++17) |
iterator |
nh пуст или
| Если nh пуст, не выполняет никаких действий и возвращает a.end(). В противном случае вставляет элемент, которым владеет nh, тогда и только тогда, когда в контейнерах с уникальными ключами нет элемента с ключом, эквивалентным nh.key(); всегда вставляет элемент, которым владеет nh, в контейнерах с эквивалентными ключами. Итератор q является подсказкой, указывающей, откуда должен начинаться поиск. Реализациям разрешено игнорировать подсказку. Гарантии: nh пуст в случае успешной вставки, не изменяется в случае неудачной вставки | Итератор, указывающий на элемент с ключом, эквивалентным nh.key() | В среднем O(1), в худшем случае O(a.size()) |
a.extract(k)(начиная с C++17) |
node_type | Удаляет из контейнера элемент с ключом, эквивалентным k | Объект node_type, владеющий элементом, если он найден, в противном случае — пустой node_type | В среднем O(1), в худшем случае O(a.size()) |
|
a_tran.extract(kx)(начиная с C++23) |
node_type | Удаляет из контейнера элемент с ключом, эквивалентным kx | Объект node_type, владеющий элементом, если он найден, в противном случае — пустой node_type | В среднем O(1), в худшем случае O(a_tran.size()) |
|
a.extract(q)(начиная с C++17) |
node_type | Удаляет элемент, на который указывает q | Объект node_type, владеющий этим элементом | В среднем O(1), в худшем случае O(a.size()) |
|
a.merge(a2)(начиная с C++17) | void |
a.get_allocator()==a2.get_allocator() | Пытается извлечь каждый элемент из a2 и вставить его в a, используя функцию хеширования и предикат равенства ключей объекта a. В контейнерах с уникальными ключами, если в a есть элемент с ключом, эквивалентным ключу элемента из a2, то этот элемент не извлекается из a2. Гарантии: Указатели и ссылки на перемещенные элементы a2 ссылаются на те же самые элементы, но как на члены a. Итераторы, ссылающиеся на перемещенные элементы, и все итераторы, ссылающиеся на a, будут инвалидированы, однако итераторы элементов, оставшихся в a2, останутся действительными | В среднем O(N), где N — это a2.size(), в худшем случае O(N·(a.size() + 1)) |
|
a.erase(k) |
size_type | Стирает все элементы с ключом, эквивалентным k | Количество стертых элементов | В среднем O(a.count(k)), в худшем случае O(a.size()) |
|
a_tran.erase(kx)(начиная с C++23) |
size_type | Стирает все элементы с ключом, эквивалентным kx | Количество стертых элементов | В среднем O(a_tran.count(kx)), в худшем случае O(a_tran.size()) |
|
a.erase(q) |
iterator | Стирает элемент, на который указывает q | Итератор, непосредственно следующий за q до стирания | В среднем O(1), в худшем случае O(a.size()) |
|
a.erase(r)(начиная с C++17) |
iterator | Стирает элемент, на который указывает r | Итератор, непосредственно следующий за r до стирания | В среднем O(1), в худшем случае O(a.size()) |
|
a.erase(q1, q2) |
iterator | Стирает все элементы в диапазоне[q1, q2) | Итератор, непосредственно следующий за стертыми элементами до стирания | В среднем линейная от std::distance(q1, q2), в худшем случае O(a.size()) |
|
a.clear() | void | Стирает все элементы в контейнере. Гарантии: a.empty() равен true | Линейная от a.size() |
||
b.find(k) |
iterator; const_iterator для константного b | Итератор, указывающий на элемент с ключом, эквивалентным k, или b.end(), если такого элемента не существует | В среднем O(1), в худшем случае O(b.size()) |
||
a_tran.find(ke)(начиная с C++17)? |
iterator; const_iterator для константного a_tran | Итератор, указывающий на элемент с ключом, эквивалентным ke, или a_tran.end(), если такого элемента не существует | В среднем O(1), в худшем случае O(a_tran.size()) |
||
b.count(k) |
size_type | Количество элементов с ключом, эквивалентным k | В среднем O(b.count(k)), в худшем случае O(b.size()) |
||
a_tran.count(ke)(начиная с C++17)? |
size_type | Количество элементов с ключом, эквивалентным ke | В среднем O(a_tran.count(ke)), в худшем случае O(a_tran.size()) |
||
b.contains(k)(начиная с C++20)? |
b.find(k) != b.end() | ||||
a_tran.contains(ke)(начиная с C++20)? |
a_tran.find(ke) != a_tran.end() | ||||
b.equal_range(k) | std::pair< iterator, iterator>; std::pair< | Диапазон, содержащий все элементы с ключами, эквивалентными k. Возвращает
| В среднем O(b.count(k)), в худшем случае O(b.size()) |
||
a_tran.equal_range(ke)(начиная с C++20)? | std::pair< iterator, iterator>; std::pair< | Диапазон, содержащий все элементы с ключами, эквивалентными ke. Возвращает
| В среднем O(a_tran.count(ke)), в худшем случае O(a_tran.size()) |
||
b.bucket_count() |
size_type | Количество корзин, содержащихся в b | Константная | ||
b.max_bucket_count() |
size_type | Верхняя граница количества корзин, которое когда-либо может содержать b | Константная | ||
b.bucket(k) |
size_type |
b.bucket_count() > 0 | Индекс корзины, в которой будут найдены элементы с ключами, эквивалентными k, если таковые существуют. Возвращаемое значение находится в диапазоне [0, b.bucket_count()) | Константная | |
a_tran.bucket(ke) |
size_type |
a_tran.bucket_count() > 0 | Индекс корзины, в которой будут найдены элементы с ключами, эквивалентными ke, если таковые существуют. Возвращаемое значение должно находиться в диапазоне [0, a_tran.bucket_count()) | Константная | |
b.bucket_size(n) |
size_type |
n находится в [0, b.bucket_count()) | Количество элементов в n-й корзине | O(b.bucket_size(n)) |
|
b.begin(n) |
local_iterator; const_local_iterator для константного b |
n находится в [0, b.bucket_count()) | Итератор, ссылающийся на первый элемент в корзине. Если корзина пуста, то b.begin(n) == b.end(n) | Константная | |
b.end(n) |
local_iterator; const_local_iterator для константного b |
n находится в [0, b.bucket_count()) | Итератор, представляющий собой значение за концом корзины (past-the-end) | Константная | |
b.cbegin(n) |
const_local_iterator |
n находится в [0, b.bucket_count()) | Итератор, ссылающийся на первый элемент в корзине. Если корзина пуста, то b.cbegin(n) == b.cend(n) | Константная | |
b.cend(n) |
const_local_iterator |
n находится в [0, b.bucket_count()) | Итератор, представляющий собой значение за концом корзины (past-the-end) | Константная | |
b.load_factor() | float | Среднее количество элементов на корзину | Константная | ||
b.max_load_factor() | float | Положительное число, ниже или равное которому контейнер старается удерживать коэффициент заполнения. Контейнер автоматически увеличивает количество корзин по мере необходимости, чтобы коэффициент заполнения оставался ниже этого числа | Константная | ||
a.max_load_factor(z) | void |
z положителен. Может изменять максимальный коэффициент заполнения контейнера, используя z в качестве подсказки | Константная | ||
a.rehash(n) | void | Гарантии:
| В среднем линейная от a.size(), в худшем случае O(N2) |
||
a.reserve(n) |
a.rehash(std::ceil(n / a.max_load_factor())) |
Стандартная библиотека
Следующие контейнеры стандартной библиотеки удовлетворяют требованиям UnorderedAssociativeContainer:
|
(C++11) | совокупность уникальных ключей с хешированием по ключам (шаблон класса) |
|
(C++11) | совокупность ключей с хешированием по ключам (шаблон класса) |
|
(C++11) | совокупность пар «ключ — значение» с хешированием по ключам; ключи уникальны (шаблон класса) |
|
(C++11) | совокупность пар «ключ — значение» с хешированием по ключам (шаблон класса) |
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Опубликованное поведение | Правильное поведение |
|---|---|---|---|
| LWG 2156 | C++11 | коэффициент загрузки после перехеширования мог быть только строго меньше максимального коэффициента загрузки | допускается равенство |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/named_req/UnorderedAssociativeContainer