Известен ли порядок итерации через std::map (и гарантирован стандартом)?

что я имею в виду - мы знаем, что сортируются в соответствии с ключами. Итак, предположим, что ключи являются целыми числами. Если я повторяю из std::map::begin() to std::map::end() С помощью for, гарантирует ли стандарт, что я буду последовательно перебирать элементы с ключами, отсортированными в порядке возрастания?


пример:

std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
     iter != map_.end();
     ++iter )
{
    std::cout << iter->second;
}

это гарантировано для печати 234 или это определенная реализация?


реальная причина жизни: я есть std::map С int ключи. В очень редких ситуациях я хотел бы перебрать все элементы с ключом, большим, чем конкретный int значение. Да, похоже на std::vector было бы лучшим выбором, но обратите внимание на мои "очень редкие ситуации".


редактировать: я знаю, что элементы std::map сортируются.. нет необходимости указывать на это (для большинства ответов здесь). Я даже написал это в своем вопросе.
Я спрашивал об итераторах и порядке когда я перебираю контейнер. Спасибо @Kerrek SB за ответ.

5 ответов


Да, это гарантировано. Более того,*begin() дает вам самый маленький и *rbegin() самый большой элемент, как определено оператором сравнения, и два ключевых значения a и b для которого выражение !compare(a,b) && !compare(b,a) справедливо считаются равными. По умолчанию используется функция сравнения std::less<K>.

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


это гарантируется ассоциативными требованиями к контейнерам в стандарте C++. Е. Г. увидеть 23.2.4/10 в C++11:

The fundamental property of iterators of associative containers is that they
iterate through the containers in the non-descending order of keys where
non-descending is defined by the comparison that was used to construct them.
For any two dereferenceable iterators i and j such that distance from i to j is
positive,
  value_comp(*j, *i) == false

и 23.2.4/11

For associative containers with unique keys the stronger condition holds,
  value_comp(*i, *j) != false.

я думаю, что есть путаница в структурах данных.

в большинстве языков a map - Это просто AssociativeContainer: он сопоставляет ключ со значением. В" новых " языках это обычно достигается с помощью хэш-карты, поэтому порядок не гарантируется.

в C++, однако это не так:

  • std::map это отсортированный ассоциативный контейнер
  • std::unordered_map - ассоциативный контейнер на основе хэш-таблицы, введенный в C++11

Итак, чтобы уточнить гарантии при заказе.

В C++03:

  • std::set, std::multiset, std::map и std::multimap гарантированно быть приказанным согласно ключам (и поставленному критерию)
  • на std::multiset и std::multimap, стандарт не налагает никакой гарантии порядка на эквивалентные элементы (т. е. те, которые сравниваются равными)

In C++11:

  • std::set, std::multiset, std::map и std::multimap гарантированно быть приказанным согласно ключам (и поставленному критерию)
  • на std::multiset и std::multimap стандартный предусматривает что эквивалентные элементы (те, которые сравниваются равными) упорядочены в соответствии с их порядком вставки (сначала вставлены первыми)
  • std::unordered_* контейнеры, как следует из названия, не упорядочены. Прежде всего, порядок элементов мая изменение при изменении контейнера (при вставке/удалении).

когда стандарт говорит, что элементы упорядочены таким образом, это означает, что:

  • при итерации вы видите элементы в определенном порядке
  • при итерации в обратном порядке вы видите элементы в обратном порядке

надеюсь, это прояснит любую путаницу.


гарантируется ли печать 234 или определена реализация?

да std::map сортированный контейнер, приказанный Key с предоставленным Comparator. Так что это гарантировано.

Я хотел бы пройти итерацию через все элементы с ключом, большим, чем конкретное значение int.

это, безусловно, возможно.


да ... элементов std::map строгий слабый заказ, это означает, что элементы будут состоять из набора (т. е., не будет никаких повторов ключей, которые "равны"), и равенство определяется тестированием на любые две клавиши A и B, что если ключ не меньше B, А B не меньше, чем a, то ключ равен ключевых Б.

это, как говорится, вы не можете правильно сортировать элементы std::map Если слабый порядок для этого типа неоднозначен (в вашем случае, где вы используете целые числа в качестве типа ключа, это не проблема). Вы должны иметь возможность определить операцию, которая определяет общий порядок для типа, который вы используете для ключей в вашем std::map, в противном случае у вас будет только частичный порядок для ваших элементов или poset, который имеет свойство, где A может быть не сопоставим с B. что обычно происходит в этом сценарии, так это то, что вы сможете вставить пары ключ/значение, но вы можете получить дубликаты пар ключ / значение, если вы повторите вся карта и/или обнаружение "отсутствующих" пар ключ / значение при попытке выполнить std::map::find() определенной пары ключ / значение на карте.