3

We (all) know, erasing an element, pointer by an iterator invalidates the iterator, for example:

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

But, what about:

map_.erase( map_.begin() );

is this safe? Will map_.begin() be a valid iterator, pointing to the (new) first element of the map?

"test it" is not a solution.

Kiril Kirov
  • 37,467
  • 22
  • 115
  • 187

4 Answers4

4

begin() is not an iterator but returns an iterator. After erasing the first element, begin()returns another (valid) iterator.

 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
hansmaad
  • 18,417
  • 9
  • 53
  • 94
  • Aha, seems like this one is what I was (somehow) missing: "begin() is not an iterator but returns an iterator". – Kiril Kirov May 22 '13 at 10:44
3

On cppreference, we see:

All iterators (pos, first, last) must be valid and dereferenceable, that is, the end() iterator (which is valid, but is not dereferencable) cannot be used.

That pretty much answers your question. As long as the iterator returned by begin() is valid and dereferencable, it is OK to be used in std::map::erase(). A good way then to check if begin() is OK to be used in std::map::erase is by checking it if it is not equal to end():

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

Alternatively, you could also check if the map is empty, and use std::map::erase if it isn't

if(!map.empty()) {
   map.erase(map.begin());
}
Mark Garcia
  • 17,424
  • 4
  • 58
  • 94
2

Of course it is.

map::begin returns a valid iterator referring to the first element in the map container. http://www.cplusplus.com/reference/map/map/begin/

Pay attention to empty map.

Nicola Pezzotti
  • 2,317
  • 1
  • 16
  • 26
1

is this safe?

Yes. It invalidates the temporary iterator returned by this call to begin(), and that iterator is destroyed at the end of the statement.

Will map_.begin() be a valid iterator, pointing to the (new) first element of the map?

Yes, unless the map is now empty. Erasing an element does not prevent you from creating new iterators to the remaining elements; that would make the map unusable.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644