我们(都)知道,擦除一个元素,迭代器的指针会使迭代器无效,例如:
std::map< .. > map_;
std::map< .. >::iterator iter;
// ..
map_.erase( iter ); // this will invalidate `iter`.
但是关于:
map_.erase( map_.begin() );
这安全吗?将map_.begin()
是一个有效的迭代器,指向地图的(新)第一个元素?
“测试它”不是解决方案。
我们(都)知道,擦除一个元素,迭代器的指针会使迭代器无效,例如:
std::map< .. > map_;
std::map< .. >::iterator iter;
// ..
map_.erase( iter ); // this will invalidate `iter`.
但是关于:
map_.erase( map_.begin() );
这安全吗?将map_.begin()
是一个有效的迭代器,指向地图的(新)第一个元素?
“测试它”不是解决方案。
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
在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());
}
这安全吗?
是的。它使此调用返回的临时迭代器无效begin()
,并且该迭代器在语句结束时被销毁。
将
map_.begin()
是一个有效的迭代器,指向地图的(新)第一个元素?
是的,除非地图现在是空的。删除一个元素不会阻止您为剩余元素创建新的迭代器;这将使地图无法使用。