【问题标题】:Why doesn't erase support reverse iterators?为什么擦除不支持反向迭代器?
【发布时间】:2016-01-25 15:26:51
【问题描述】:

我刚刚写了下面的代码,很惊讶它没有编译:

std::deque<int> container;
// filling the container...
for (auto it = container.rbegin(); it != container.rend(); ++it)
    if (*it == 5)
    {
        container.erase(it);
        break;
    }

如您所见,我想删除最后一个符合特定条件的元素(如果有)。

错误是

没有匹配的调用函数 std::deque::erase(std::reverse_iterator...

一开始我不相信它是由反向迭代器引起的,但确实如此,因为将rbegin/rend 替换为begin/end 解决了它。

所以,两个问题:

  1. 为什么不支持此功能?这仅仅是 C++ 委员会忘记包含在标准中的那些小东西之一,还是缺少这种重载的理由?
  2. 什么是做我想做的最优雅的方式?我是否坚持按索引进行迭代?

【问题讨论】:

  • 我想你的答案就在这里:stackoverflow.com/questions/1830158/…
  • m_containercontainer一样吗?
  • @Violet - 原因rend() 不能在开始之前返回迭代器,因为没有类似的东西。所以它改为持有 begin() 并将其所有访问调整 1 以进行补偿。
  • @VioletGiraffe 你说得对,我是个白痴。尽管如此,本着尽可能使用&lt;algorithm&gt; 的精神,我还是建议使用erasefind_if(container.rbegin()... 的结果(即使它不会减少行数)。
  • @screwnut 不,我认为您坚持将 OP 从清晰、易于理解的代码切换到更神秘的代码,这绝对没有充分的理由。你的第一个建议甚至是悲观的。重点是什么? “本着尽可能使用 的精神” Cargo cult programming = bad.

标签: c++ containers erase


【解决方案1】:

我认为,在没有“需要”的情况下,需要在整个标准库中添加的额外重载数量使这项任务变得不合时宜。

当然,“最优雅”的解决方法很难表达:

container.erase((it+1).base());

…但是一个,并且反向迭代器的使用频率可能不足以保证所有额外的噪音,这些噪音是由于到处都有重载而导致的,除了包装上面的代码行之外什么都不做。

如果你发现自己经常使用它,你可以自己包装更通用的解决方案:

template <typename ReverseIterator>
auto AsForwardIterator(ReverseIterator rit)
{
    std::advance(rit, 1);
    return rit.base();
}

那就是:

container.erase(AsForwardIterator(it));

而且,坦率地说,这样做的简单性似乎不值得在每个容器中都包含所有这些重载。

【讨论】:

    【解决方案2】:

    我无法回答“为什么”问题,但要回答“如何” - 您应该在迭代器上调用 base()。它将返回一个正确的前向迭代器。

    这样做时,请记住反向迭代器和正向迭代器之间的关系。一开始可能会令人困惑,但实际上很简单。如果您有一个包含以下项目的std::vector

    1, 2, 3, 4, 5
    

    你有一个reverse_iterator rit,它在解除引用时给你 3,然后*(rit.base) 将等于 4。要了解原因,请记住在普通迭代器中 begin() 是可取消引用的,但 end() 是不是。在反向迭代器中,属性必须相同 - rbegin() 必须是可取消引用的,但 rend() 不应该 - 即,应该指向容器的开头之外。

    因为根据定义,rend.base()begin() 相同(因为rend 可以构造为reverse_iterator(begin()),所以以上所有内容的唯一方法是,如果rend.base() 将返回下一个右元素到开始之后的那个 - begin()。很容易看出,rend() 具有相同的对称性。

    【讨论】:

    • 否决了答案,因为您不能简单地将 reverse_iterator::base() 传递给 erase 方法。
    • @VioletGiraffe,为什么?
    • 因为它会擦除错误的元素!迭代器必须先调整1。
    • @VioletGiraffe,定义错误。它会删除你的反向迭代器当前指向的元素。
    • 不,请参阅建议的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 2021-01-02
    • 2023-03-26
    • 1970-01-01
    • 2021-03-18
    • 2016-09-03
    相关资源
    最近更新 更多