Одинаков ли порядок двух одинаковых unordered_maps?

Другими словами, если я заполню два объекта unordered_map или unordered_set абсолютно одинаковым содержимым и одной и той же хеш-функцией, будет ли их перебор давать одинаковую последовательность пар ключ/значение?

Если да, то каковы условия для этого (например, одна и та же функция хэширования, одни и те же ключи, не обязательно одинаковые значения).


person pms    schedule 24.03.2012    source источник
comment
Хеш-функция, о которой вы думаете, на самом деле не является последней используемой хэш-функцией. Размер корзины может изменяться динамически, а фактическая хэш-функция выводится из вашей хеш-функции (предположительно, каким-то модульно-арифметическим способом).   -  person Kerrek SB    schedule 25.03.2012


Ответы (4)


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

person David Schwartz    schedule 24.03.2012
comment
Если вы добавляете элементы с одними и теми же ключами в одном и том же порядке с одной и той же функцией хэширования в один и тот же размер контейнера (т. е. не делаете ничего странного с reserve или чем-то еще), что может заставить их упорядочиваться по-разному? - person Seth Carnegie; 25.03.2012
comment
Да, так.. вот о чем я спрашиваю. Хотя это и не указано, на практике же оно указано, не так ли? :) - person pms; 25.03.2012
comment
@SethCarnegie: Во-первых, ОП не сказал, что они будут добавлены в том же порядке. Во-вторых, что угодно может заставить их упорядочиваться по-другому. Реализация может, если захочет, упорядочить их случайным образом или даже переупорядочить, чтобы наиболее часто используемые объекты помещались первыми в их хеш-цепочках. - person David Schwartz; 25.03.2012

Поведение в этом случае не определено. Так вот, в одних ситуациях последовательность будет одинаковая, в других - другая. Ни в чем нельзя быть уверенным. Упомянутые вами типы названы unordered не случайно. Использовать их по заказу — очень-очень плохой и крайне опасный стиль.

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

То, что просто запрещено в других языках, в C/C++ не указано. Но вы также должны воспринимать это как запретное.

Посмотрите c-faq о проблеме неопределенного поведения Эта концепция общая для всех C/C++

person Gangnus    schedule 24.03.2012
comment
Да... но из того, что я могу прочитать здесь, кажется, что это возможно... - person pms; 25.03.2012
comment
Возможно так. Но можно и не так. То, что просто запрещено в других языках, в C/C++ не указано. Но вы также должны воспринимать это как запретное. - person Gangnus; 25.03.2012
comment
@pms: То, что неупорядочено, означает ненадежно упорядочено. Это означает, что спецификация C++ не будет определять порядок. Ваша реализация std::unordered_* действительно может иметь некоторый последовательный порядок. Но спецификация не применяет это. Принимая во внимание, что он обеспечивает определенный порядок на std::map. Поэтому, если вы хотите, чтобы ваш код был переносимым, вы не можете полагаться на порядок. - person Nicol Bolas; 25.03.2012

Ну, сначала я процитирую MSDN:

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

Приведенная выше цитата одинакова для unordered_map и unordered_set, и, как следует из названия, последовательность не указана, однако они упоминают, что эквивалентные ключи являются смежными.

person Jesse Good    schedule 24.03.2012
comment
Я думаю, что это только для реализации MS, не так ли? Или это требование стандарта? Похоже, что это заставит реализации использовать линейное зондирование для коллизий (или сохранять каждый элемент в косвенном динамическом массиве). - person Seth Carnegie; 25.03.2012
comment
@SethCarnegie: кажется, это необходимо, я нашел обсуждение по этому поводу здесь (см. пост 6). - person Jesse Good; 25.03.2012
comment
Мы говорим о разнице между специфичным для компилятора и неопределенным поведением - в терминах стандарта C/C++ ANSI. Любые тексты MS могут быть очень полезны для своих конкретных нужд, но здесь работают только как сравнительный пример. - person Gangnus; 12.06.2018
comment
Ссылка во втором комментарии теперь 404. Что касается других комментариев, я не очень понимаю возражения здесь. До тех пор, пока реализация MS соответствует требованиям (а это, конечно, следует предполагать), тогда сделанные ею допуски на вариации свидетельствуют об отсутствии ограничений, налагаемых Стандартом. Указание абсолютного разнообразия вещей, которые могут влиять на порядок, без определения того, как они действуют, не противоречит Стандарту, избегающему определенного порядка. И эквивалентное сравнение смежных элементов является простым фактом реализации корзины/цепочки, что, очевидно, требует Стандарт. - person underscore_d; 03.01.2019

Если вам нужен гарантированный порядок, эта структура данных не для вас. На самом деле, если вы в основном собираетесь выполнять итерацию, unordered_map/set также не является для вас структурой данных.

Для итерации std::map окажется лучшей структурой данных, поскольку переход от одного узла к другому менее алгоритмически сложен. И порядок итерации для объектов в std::map задается спецификацией (и на самом деле является определяющим свойством самой структуры). (Это все при условии, что вы используете один и тот же оператор сравнения, очевидно). В std::map не используется хеширование.

Достаточно сказать, похоже, что вы лаете не на то дерево. unordered_map обычно следует использовать для таких преимуществ, как поиск O (1), а не для хранения списка объектов, а затем для их повторения. Его определенно не следует использовать, если вы пытаетесь получить детерминированный порядок итераций.

person Mahmoud Al-Qudsi    schedule 25.03.2012
comment
Конечно, нет. Но если это чувствительная к производительности часть вашего кода, это может быть единственное, что вы делаете. - person Mahmoud Al-Qudsi; 25.03.2012
comment
Это не так, я использую хэш-таблицы по какой-то причине, и вы упускаете суть. - person pms; 25.03.2012
comment
Если вы думаете, что мой пост упустил суть, я думаю, вы что-то упускаете. - person Mahmoud Al-Qudsi; 25.03.2012
comment
Что ж, я ценю ваш ответ и советы, но ваш пост явно не отвечает на вопрос, заданный здесь: Является ли порядок двух одинаковых unordered_maps одинаковым? Если это причина, по которой вы проголосовали за мой вопрос, то я нахожу его агрессивным, и вам, вероятно, следует пересмотреть свое отношение. Заботиться. - person pms; 26.03.2012
comment
Я очень просто ответил на ваш вопрос: заказ НЕ гарантируется. Насколько сложно это передать?!? - person Mahmoud Al-Qudsi; 27.03.2012
comment
Не совсем, вы писали: Если вам нужен гарантированный порядок, то эта структура данных не для вас. Вы использовали здесь условное выражение, потому что предположили, что мне нужен гарантированный порядок, а это не обязательно верно. Здесь важен только вопрос. - person pms; 27.03.2012