发生擦除和push_back时如何正确擦除reverse_iterator?

How to erase reverse_iterator correctly when erase and push_back happens?

我有一个列表容器,它看起来像:

std::list<int> l = {1,2,3,4,5,6,7,8};

我经常删除元素,所以我选择std::list

但是,我也想在 O(1) 中找到元素,所以我记录了 reverse_iterator。

例如:

  l.push_back(9);
  auto s = l.rbegin();  // record the iterator of 9, in order to erase it in the future fastly.
  cout << *s << endl;
  l.push_back(10);
  auto s2 = l.rbegin();

但是当我这样擦除时:

l.erase(std::next(s).base());  // s the iterator of 9, in my brain

我想擦掉9,结果擦掉了10

我有两个问题:

为什么我应该使用 next?其实我的*s可以获取到元素,这和.end().

不一样

如何在我之前保存的迭代器中进行擦除?

因为list的迭代器是双向迭代器,不用reverse_iterator,你可以只用--l.end()得到最后一个值的迭代器。

std::list<int> l = {1,2,3,4,5,6,7,8};
l.push_back(9);
auto s = --l.end(); // record the iterator of 9
l.push_back(10);
l.erase(s); // erase the iterator of 9

Demo.

l.rbegin().base() == l.end(),这不是最后一个元素的位置,而是列表的末尾。并且 push_back 也不会影响这个现有的迭代器,它仍然指向列表的末尾。

然后 std::next(l.rbegin()).base() == l.end() - 1,现在指向最后一个元素 10

所以如果你想记住 9 的位置,你最好使用普通迭代器而不是反向迭代器,或者,使用基指向 9 的反向迭代器,以及那应该是 auto s = std::next(l.rbegin()),并将其删除为 l.erase(s.base())

规则是&*r == &*(i-1)