std :: vector迭代器失效

Cha*_*l72 14 c++ iterator stl vector

之前有一些关于这个问题的问题; 我的理解是,调用std::vector::erase只会使处于擦除元素之后的位置的迭代器无效.但是,在擦除元素之后,该位置的迭代器是否仍然有效(当然,前提是它end()在擦除后没有指向)?

我对如何实现向量的理解似乎表明迭代器肯定是可用的,但我不完全确定它是否会导致未定义的行为.

作为我正在谈论的一个例子,下面的代码从向量中删除所有奇数整数.此代码是否会导致未定义的行为?

typedef std::vector<int> vectype;
vectype vec;

for (int i = 0; i < 100; ++i) vec.push_back(i);

vectype::iterator it = vec.begin();
while (it != vec.end()) {
    if (*it % 2 == 1) vec.erase(it);
    else ++it;
}
Run Code Online (Sandbox Code Playgroud)

代码在我的机器上正常运行,但这并不能说服它是有效的.

Jam*_*lis 36

擦除元素后,该位置的迭代器仍然有效

没有; 传递给它的迭代器之后或之后的所有迭代器erase都是无效的.

但是,erase返回一个新的迭代器,它指向被删除的元素之后的元素(如果没有这样的元素,则指向结尾).您可以使用此迭代器继续迭代.


请注意,这种删除奇数元素的特殊方法效率非常低:每次删除元素时,其后的所有元素都必须在向量中向左移动一个位置(这是O(n 2)).您可以使用erase-remove惯用法(O(n))更有效地完成此任务.您可以创建is_odd谓词:

bool is_odd(int x) { return (x % 2) == 1; }
Run Code Online (Sandbox Code Playgroud)

然后这可以传递给remove_if:

vec.erase(std::remove_if(vec.begin(), vec.end(), is_odd), vec.end());
Run Code Online (Sandbox Code Playgroud)