Spec-Zone.ru › C++

Именованные требования C++: UnorderedAssociativeContainer (начиная с C++11)

Неупорядоченные ассоциативные контейнеры — это контейнеры, обеспечивающие быстрый поиск объектов по ключам. В худшем случае сложность линейная, но в среднем большинство операций выполняется гораздо быстрее.

Неупорядоченные ассоциативные контейнеры параметризуются Key; Hash — объектом-функцией хеширования, которая используется как хеш-функция для Key; и Pred — объектом-функцией бинарного предиката, определяющим эквивалентность между Keys. std::unordered_map и std::unordered_multimap также имеют тип отображаемого значения T, связанный с Key.

Если согласно Pred два Keys равны, Hash должен возвращать одинаковое значение для обоих ключей.

Если существуют и обозначают типы и Hash::is_transparent, и Pred::is_transparent, функции-члены find, contains, count, equal_range и bucket принимают аргументы типов, отличных от Key, и предполагают, что Hash вызываема со значениями этих типов, а Pred является прозрачной функцией сравнения, такой как std::equal_to<>.

(начиная с 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 Значение, для которого
  • eq(r1, ke) == eq(ke, r1),
  • hf(r1) == hf(ke), если eq(r1, ke) — это true, и
  • если любые два из eq(r1, ke), eq(r2, ke) и eq(r1, r2) являются true, то все три являются true,

где r1 и r2 — ключи элементов в a_tran

kx (начиная с C++23) Значение, для которого
  • eq(r1, kx) == eq(kx, r1),
  • hf(r1) == hf(kx), если eq(r1, kx) — это true,
  • если любые два из eq(r1, kx), eq(r2, kx) и eq(r1, r2) являются true, то все три являются true, и
  • kx не преобразуется ни в iterator, ни в const_iterator,

где r1 и r2 — ключи элементов в a_tran

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 пуст или

a_uniq.get_allocator()==nh.get_allocator() равен true

Если 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 пуст или

a_eq.get_allocator()==nh.get_allocator() равен true

Если nh пуст, не выполняет никаких действий и возвращает a_eq.end(). В противном случае вставляет элемент, которым владеет nh, и возвращает итератор, указывающий на вставленный элемент. Гарантии: nh пуст В среднем O(1), в худшем случае O(a_eq.size())
a.insert(q, nh)
(начиная с C++17)
iterator nh пуст или

a.get_allocator()==nh.get_allocator() равен true

Если 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<
const_iterator,
const_iterator> для константного b

Диапазон, содержащий все элементы с ключами, эквивалентными k. Возвращает

std::make_pair(b.end(), b.end()), если такие элементы отсутствуют

В среднем O(b.count(k)), в худшем случае O(b.size())
a_tran.equal_range(ke)
(начиная с C++20)?
std::pair<
iterator,
iterator>;

std::pair<
const_iterator,
const_iterator> для константного a_tran

Диапазон, содержащий все элементы с ключами, эквивалентными ke. Возвращает

std::make_pair(a_tran.end(),a_tran.end()), если такие элементы отсутствуют

В среднем 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.bucket_count() >=a.size() / a.max_load_factor() и a.bucket_count() >= n

В среднем линейная от a.size(), в худшем случае O(N2)
a.reserve(n) a.rehash(std::ceil(n / a.max_load_factor()))

Стандартная библиотека

Следующие контейнеры стандартной библиотеки удовлетворяют требованиям UnorderedAssociativeContainer:

unordered_set
(C++11)
совокупность уникальных ключей с хешированием по ключам
(шаблон класса)
unordered_multiset
(C++11)
совокупность ключей с хешированием по ключам
(шаблон класса)
unordered_map
(C++11)
совокупность пар «ключ — значение» с хешированием по ключам; ключи уникальны
(шаблон класса)
unordered_multimap
(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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API