我们都知道当使用erase in时,我们必须重置iter,就像iter = vector.erase(iter)一样,因为erase选项会使iteraor无效。但我发现,不重置也有效,下面的代码:
int main() {
vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(2);
a.push_back(10);
a.push_back(11);
for (vector<int>::iterator iter = a.begin(); iter != a.end();) {
if (*iter == 2) {
// iter = a.erase(iter); the same
a.erase(iter);
continue;
} else {
iter++;
}
}
for (vector<int>::iterator iter = a.begin(); iter != a.end(); iter++) {
cout << *iter << " ";
}
cout << endl;
return 0;
}
代码成功运行,输出:1 3 10 11。
所以我的问题是“a.erase(iter)”与此代码中的“iter = a.earse(iter)”得到相同的结果?
答案 0 :(得分:3)
您所看到的是未定义的行为。
来自http://en.cppreference.com/w/cpp/container/vector/erase(强调我的)
从容器中删除指定的元素 1)移除pos处的元素 2)删除
[first; last)
范围内的元素。在擦除</ strong>之后或之后使迭代器和引用无效,包括end()迭代器。
使用
a.erase(iter);
continue;
您正在访问无效的迭代器。
答案 1 :(得分:2)
您的代码依赖于向量的元素减少而不是执行保留减少以消除不需要的容量。坦率地说,我使用的几乎所有标准库实现都是这样做的(减小大小值并将元素转移到“left”),但标准保证不以这种方式表现。相反,情况正好相反。擦除当前迭代器位置后,该迭代器和过去的任何其他位置都无效。因此,您的代码展示未定义的行为。
关于标准明确指出迭代器变为无效的地方:
C ++11§23.3.6.5[vector.modifiers]
...
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
- 效果:在删除点或之后使迭代器和引用无效。
- 复杂性:T的析构函数被称为等于被擦除元素数量的次数,但T的移动赋值运算符被称为等于被擦除元素后向量中元素数量的次数
- 抛出:除非复制构造函数,移动构造函数,赋值运算符或T的移动赋值运算符抛出异常,否则无效。
但我很好奇:你为什么不只是使用remove/erase idiom?:
a.erase(std::remove(a.begin(), a.end(), 2), a.end());