简体   繁体   English

从向量中删除最后一个元素会导致迭代出现问题

[英]Erasing the last element from the vector, causes problems in iterating

Here's my code:这是我的代码:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
v.push_back(5);
v.push_back(6);
v.push_back(7);

for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{
    if (*it == 7)
        v.erase(it);
    cout << *it << endl;
}

The issue is, the for loop does not stop running and prints garbage values.问题是, for循环不会停止运行并打印垃圾值。 Can you give some insight on the issue...like maybe the last element stores information about size or the address of the end() ?您能否就此问题提供一些见解...比如最后一个元素可能存储有关大小或end()地址的信息?

Using the erase() method works fine for other locations in the vector, except the last element.使用erase()方法可以很好地处理向量中的其他位置,但最后一个元素除外。

The console log shows garbage values like this:控制台日志显示如下垃圾值:

34603778
35652354
50397954
34603592
34603536
34603536
34603536
34603536
34603794
36700688
34603536
34603536
34865684
51511824
34603536
34865680

Your program has undefined behavior no matter what position you erase from in your vector.无论您从矢量中的哪个位置擦除,您的程序都有未定义的行为。 As the documentation says, the function:正如文档所说,该功能:

Invalidates iterators and references at or after the point of the erase, including the end() iterator.使擦除点处或擦除点之后的迭代器和引用无效,包括 end() 迭代器。

So, your iterator is dead the moment you erase.所以,你的迭代器在你擦除的那一刻就死了。 This is why the function returns a new iterator (to the item that is now in the position you just erased from).这就是为什么该函数返回一个新的迭代器(返回到现在位于您刚刚删除的位置的项目)的原因。 You must update your loop's iterator to use that.您必须更新循环的迭代器才能使用它。

The idiomatic way to erase from a standard container in a loop is to step the iterator in the loop body itself:从循环中的标准容器中擦除的惯用方法是将迭代器步进循环体本身:

for (vector<int>::iterator it = v.begin(); it != v.end(); )
{
    if (*it == 7) {
        it = v.erase(it);
    } else {
        cout << *it << endl;
        ++it;
    }
}

However, this is not a great way in general to remove items from a vector.但是,这通常不是从矢量中删除项目的好方法。 What if the vector contains lots of values to remove?如果向量包含很多要删除的值怎么办? Your operation becomes very inefficient, because each erase must shuffle the remaining items in the vector.您的操作变得非常低效,因为每次擦除都必须打乱向量中的剩余项目。

So the better approach is the erase-remove idiom :所以更好的方法是erase-remove 习惯用法

v.erase(std::remove(v.begin(), v.end(), 7), v.end());

Since C++20, this is simplified further :从 C++20 开始,这进一步简化了

std::erase(v, 7);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM