【问题标题】:Erase-remove idiom: what happens when remove return past-the-end-iterator?Erase-remove 习惯用法:remove return past-the-end-iterator 时会发生什么?
【发布时间】:2010-12-13 07:07:54
【问题描述】:

我在阅读 Scott Meyers "Effective STL” 书的 erase-remove idiom(第 32 项)时遇到了这个问题。

vector<int> v; 
...
v.erase(remove(v.begin(), v.end(), 99), v.end());

remove 基本上返回“新的逻辑结束”和从该范围的“新的逻辑结束”开始并一直持续到该范围的真正结束的原始范围的元素是要从容器中删除的元素。

听起来不错。现在,让我问我的问题:

在上面的示例中,如果在vector v 中找不到 99,remove 可以返回 v.end()。它基本上是将past-the-end-iterator 传递给擦除方法。

  1. past-the-end-iterator 被传递给erase 方法时会发生什么?标准是否说它是UB?
  2. 如果是未定义的行为,那么 Scott Meyer 书中的 erase-remove idiom 示例应该如下所示:

  vector<int> v; 
    ...
    vector<int>::iterator newEndIter = remove(v.begin(), v.end(), 99);
    if(newEndIter != v.end() )
    {
     v.erase(newEndIter, v.end();
    }  

对此有什么想法吗?

【问题讨论】:

  • 根据定义 v.end() 不是past-the-end,它是结束:x
  • @Matthieu M. 文档 std::vector::end() 说:“返回一个迭代器,引用向量容器中的过去元素。”
  • @Julien-L:这措辞不好。结束迭代器是最后一个元素。 C++ 规范真的这么说吗?这太令人惊讶了。
  • @MooingDuck 是的,这就是这里使用的措辞:cplusplus.com/reference/vector/vector/end
  • @Julien-L:该站点不仅不是 C++ 规范,而且该站点因误导甚至完全错误的信息而臭名昭著。但是,C++14 draft spec(第 23.2.1 节)确实声明“end() 返回一个迭代器,它是容器的结束值。”

标签: c++ stl erase erase-remove-idiom


【解决方案1】:

我认为v.erase(v.end(), v.end()) 会被很好地定义并且不会删除任何内容。

【讨论】:

  • 是,一个有效的迭代器在 [v.begin(), v.end()] INCLUSIVE.
【解决方案2】:

C++ 标准规定erase(q1,q2) 成员“擦除范围 [q1,q2) 中的元素”(参见第 23.1.1 节)。由于范围不包括最后一个元素,

v.erase(v.end(), v.end());

有效且不删除任何内容。

【讨论】:

  • 您可能需要解释数学符号 [x,y) 的含义。除非您拥有数学(或相关学科)学位,否则您可能不知道。
  • 真的吗?我确实有数学学位,但老实说,我一直认为这种符号是众所周知的。
  • 你可以在en.wikipedia.org/wiki/Interval_%28mathematics%29找到关于数学区间的维基百科页面
【解决方案3】:

C++ Reference 声明:

如果first==last:擦除空范围是无操作的,则迭代器first 不需要可取消引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-02
    • 2019-09-29
    • 2012-07-23
    • 1970-01-01
    • 2017-02-06
    • 2015-09-30
    • 1970-01-01
    • 2022-11-20
    相关资源
    最近更新 更多