我正在尝试删除刚刚遍历的元素。我最初忘了将s1.erase(...)的返回值存储在for循环中,以最终设置退出循环的条件。使用现在的代码方式,我希望循环无限期地继续下去。就像它最初打算的那样工作。 它看起来像std :: erase推进迭代器,并将值存储在rit中。我找不到任何解释此行为的文档。
https://en.cppreference.com/w/cpp/container/set/erase表示必须存储返回的迭代器。 set :: erase的所有参数都按值传递,那么反向迭代器如何进行高级处理?
此循环如何完成?
std::set<int> s1;
s1.insert(20);
s1.insert(30);
s1.insert(50);
auto rit = s1.rbegin();
for (; rit!= s1.rend();)
{
std::cout << "rit is " << *rit << " size is " << s1.size() << std::endl;
s1.erase(std::next(rit).base());
std::cout << "rit after erase is " << *rit << std::endl;
}
输出为
rit是50,大小是3
擦除后rit为30
rit是30,大小是2
擦除后rit为20
rit是20,大小是1
分段错误
答案 0 :(得分:2)
回想一下,reverse_iterator::base()
始终是明显迭代器值后面的一个元素。例如,在auto rit = s1.rbegin()
之后,*rit
返回最后一个元素,而rit.base() == s1.end()
返回。
换句话说,*rit == *prev(rit.base())
在循环中,最初为rit.base() == s1.end()
。然后std::next(rit).base()
指向最后一个元素;该元素被删除。在std::set
中,删除元素只会使对该元素的迭代器无效,而对其他元素则无效。 s1.end()
仍然是有效的迭代器,rit
也是有效的迭代器,其中rit.base()
仍然等于s1.end()
。因此,在循环的下一次迭代中,您将再次擦除最后一个元素,然后再次离开rit.base() == s1.end()
。依此类推。
在某些时候,最后一个元素被删除,s1
变为空,然后*rit
表现出未定义的行为。回想一下*rit == *prev(rit.base())
,但是已经没有先前的元素了。