问题描述
在擦除第一个迭代器位于最后一个迭代器之后的范围时会发生什么?
std::vector<int> v{1,2};
v.erase(
v.begin() + 1,v.begin()
);
那其他容器呢?
解决方法
在任何容器上以无效范围调用erase
是不确定的行为。实际上,如果幸运的话,它通常会使程序崩溃,或者如果不幸的话,它将破坏相邻的内存。
这对于大约接受迭代器范围的任何 API都是正确的。如果范围无效,则基础代码/算法无法知道停止条件实际上是什么。
迭代器范围界定了任何输入或算法的范围的开始和结束。 end
迭代器始终用于指示该范围的完成,并且必须始终可以通过重复递增第一个迭代器(例如,通过调用operator++
)来访问。
从LegacyInputIterator
要求开始,大多数算法都利用operator!=
来检测范围的完成。如果该范围是LegacyRandomAccessIterator
,则某些范围可以选择使用迭代器之间的距离。
无论哪种情况,此检测都需要第一个迭代器位于最后一个迭代器之前,否则代码如下:
for (auto it = first; first != last; ++first) { ... }
将永远不会到达范围的末尾,并且类似地:
auto distance = last - first;
将为迭代器之间的距离返回错误的值。