Подтвердить что ты не робот

Map.erase(map.end())?

Рассмотрим:

#include <map>

int main()
{
    std::map< int, int > m;
    m[ 0 ] = 0;
    m[ 1 ] = 1;

    m.erase( 0 );  // ok
    m.erase( 2 );  // no-op
    m.erase( m.find( 2 ) );  // boom!
}

(ОК, поэтому в заголовке говорится об удалении итератора end(), но find вернет конец() для несуществующего ключа.)

Почему стирание несуществующего ключа ОК, но стирание end() взрывается. Я не видел никакого явного упоминания об этом в стандарте?

Я пробовал это на VS2005 (генерирует исключение в конфигурации отладки) и GCC 4.0.1 (100% CPU). Это зависит от реализации?

Спасибо.

4b9b3361

Ответ 1

Для erase(key) в стандарте указано, что все элементы с ключом значения удалены. Разумеется, таких ценностей не может быть.

For erase(it) (где it - std::map::iterator), стандарт говорит, что элемент, на который указывает его, удаляется - к сожалению, если он end(), он не указывает на действительный элемент, и вы в undefined поведение, как и в случае, если вы использовали end() для любой другой операции с картой. Подробнее см. Раздел 23.1.2.

Ответ 2

end() не является интернатором на карте. Это эффективно "один конец" карты.

Версия 'итератора' хочет, чтобы итератор был на карте. "Ключевая" версия стирания выполняет поиск и защищает себя от не найденного ключа, версия итератора предполагает, что вы не пытаетесь сломать материал.

Ответ 3

Вместо примера, приведенного в предыдущем сообщении...

MapType::iterator it = the_map.find ("new_key");

// Does not exist.
if (it == the_map.end()) {
  the_map.insert (std::make_pair ("new_key", 10));
}

который выполняет два обхода дерева, используйте...

pair<MapType::iterator, bool> rc = the_map.insert(make_pair("new_key", 0));
if (rc.second)
    rc.first.second = 10;

Таким образом, вы совершаете обход одного дерева, и у вас есть итератор, готовый катиться для других вещей.

Ответ 4

Вот краткий пример того, как я использую карту STL с итераторами при удалении. Я также делаю то же самое при выполнении вставки. Лично мне нравится использовать typedef для конкретного определения карты, но выбор за вами.


typedef std::map... MapType;

MapType the_map;

MapType::iterator it = the_map.find ("key");
if (it != the_map.end()) {
  // Do something productive.
  the_map.erase (it);
}

MapType::iterator it = the_map.find ("new_key");

// Does not exist.
if (it == the_map.end()) {
  the_map.insert (std::make_pair ("new_key", 10));
}

Надеюсь, это поможет!