标准库容器允许我们使用迭代器 erase
和 first
表示的 last
范围。
std::vector<foo> bar;
// first it last it
bar.erase(bar.begin(), bar.end());
标准规定
first
迭代器必须有效且可取消引用,而 last
只需要有效。但是,如果 first == last
则 first
不需要可取消引用,因为 erase
是空操作。这意味着以下内容是合法的:bar.erase(bar.end(), bar.end());
但是,如果我只想擦除一个元素而不是一个范围,则迭代器必须有效且可取消引用,从而产生以下未定义的行为:
bar.erase(bar.end());
为什么这不只是一个空操作?这是标准委员会的疏忽,将在语言的 future 修订版中解决,还是我没有看到重点的故意设计决定?
据我所知,它没有任何好处,但在执行以下操作时会造成额外的麻烦:
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
对一块内存进行 ojit_code 来覆盖已擦除的内存而无需分支,但这只会发生在特定场景中。另请注意,与其他方式相比,从这里构建已检查的版本要容易得多:
checked_erase(Container cont, iterator it):
if it != cont.end():
cont.erase(it);
关于c++ - 删除最终迭代器是对标准的疏忽还是设计决策?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36681156/