c++ - 删除结束迭代器是对标准的疏忽还是设计决策?

标签 c++ iterator containers standards erase

标准库容器允许我们删除由迭代器firstlast 表示的范围。

std::vector<foo> bar;
//         first it     last it
bar.erase(bar.begin(), bar.end());

标准规定first 迭代器必须有效并且 可解引用,而last 只需要有效。但是,如果 first == lastfirst 不需要取消引用,因为 erase 是空操作。这意味着以下内容是合法的:

bar.erase(bar.end(), bar.end());

但是,如果我只想删除一个元素而不是一个范围,则迭代器必须是有效的并且可解引用,从而导致以下未定义的行为:

bar.erase(bar.end());

为什么这不只是空操作?这是标准委员会的疏忽,将在未来的语言修订版中解决,还是我没有看到重点的故意设计决定?

据我所知,它没有提供任何好处,但在执行以下操作时会造成额外的麻烦:

bar.erase(std::find(bar.begin(), bar.end(), thing));

最佳答案

C++ 习惯于在其标准库中留下任何额外的工作,也称为“你不用为你不用的东西付费”。在这种情况下,单迭代器版本需要将迭代器与结束迭代器进行比较。在大多数情况下,此检查是多余的,这是未使用的额外工作,尽管工作量很小。

erase(iterator it):
    if it != end: // we can't avoid this check now
        // erase element

在重载取范围的情况下,在结束前自然停止。一个简单的实现可能如下所示:

erase(iterator first, iterator last):
    while first != last:
        erase(first++);

它需要某种方式来知道何时停止删除。在某些情况下,它可能更智能,例如 memmove 内存块覆盖已删除的内存而无需分支,但这只会在特定场景中发生。


另请注意,与其他方式相比,由此构建检查版本要容易得多:

checked_erase(Container cont, iterator it):
    if it != cont.end():
        cont.erase(it);

关于c++ - 删除结束迭代器是对标准的疏忽还是设计决策?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36681156/

相关文章:

c++ - 如何用适当的容器表示冲突?

c++ - 重载 static_cast?

c++ - 用作 std::multimap 删除范围的第一个和最后一个的递增迭代器

C++ 迭代器被认为是有害的?

docker - 将构建输出从 Docker 容器写入主机

c++ - boost::unordered_map 维护插入顺序?

java - 将文本转换为可执行语句

c++ - 从输入中获取字符串的两个第一个和最后一个字符的快速方法

c++ - 命名空间范围与类内范围

java - 如何在 Java 中创建值的组合?