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). Это зависит от реализации?
Спасибо.
Ответы
Ответ 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));
}
Надеюсь, это поможет!