Безопасно ли вызывать std::map::erase с помощью std::map::begin?

Мы (все) знаем, что стирание элемента, указателя с помощью итератора делает итератор недействительным, например:

std::map< .. > map_;
std::map< .. >::iterator iter;
// ..
map_.erase( iter ); // this will invalidate `iter`.

Но что насчет:

map_.erase( map_.begin() );

это безопасно? Будет ли map_.begin() допустимым итератором, указывающим на (новый) первый элемент карты?

"проверить" - это не решение.


person Kiril Kirov    schedule 22.05.2013    source источник


Ответы (4)


begin() не является итератором, но возвращает итератор. После стирания первого элемента begin()возвращает другой (допустимый) итератор.

 std::map<int, int> m;
 m[1] = 2;
 m[2] = 3;
 m.erase(m.begin()); // <- begin() points to 1:2
 std::cout << m.begin()->second; // <- begin() points to 2:3 now
person hansmaad    schedule 22.05.2013
comment
Ага, похоже, это то, чего мне (каким-то образом) не хватало: begin() не является итератором, но возвращает итератор. - person Kiril Kirov; 22.05.2013

В cppreference мы видим:

Все итераторы (pos, first, last) должны быть действительными и допускающими разыменование, то есть итератор end() (действительный, но не допускающий разыменования) использовать нельзя.

Это в значительной степени отвечает на ваш вопрос. Пока итератор, возвращенный begin(), действителен и разыменуем, его можно использовать в std::map::erase(). Хороший способ проверить, подходит ли begin() для использования в std::map::erase, — это проверить, не равно ли оно end():

if(map.begin() != map.end()) {
   map.erase(map.begin());
}

Кроме того, вы также можете проверить, пуста ли карта, и использовать std::map::erase, если это не так.

if(!map.empty()) {
   map.erase(map.begin());
}
person Mark Garcia    schedule 22.05.2013

Конечно, это является.

map::begin возвращает действительный итератор, ссылающийся на первый элемент в контейнере карты. http://www.cplusplus.com/reference/map/map/begin/

Обратите внимание на пустую карту.

person Nicola Pezzotti    schedule 22.05.2013

это безопасно?

Да. Он делает недействительным временный итератор, возвращенный этим вызовом begin(), и этот итератор уничтожается в конце инструкции.

Будет ли map_.begin() допустимым итератором, указывающим на (новый) первый элемент карты?

Да, если только карта сейчас не пуста. Удаление элемента не мешает вам создавать новые итераторы для оставшихся элементов; это сделало бы карту непригодной для использования.

person Mike Seymour    schedule 22.05.2013