繁体   English   中英

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

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

这是我的代码:

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;
}

问题是, for循环不会停止运行并打印垃圾值。 您能否就此问题提供一些见解...比如最后一个元素可能存储有关大小或end()地址的信息?

使用erase()方法可以很好地处理向量中的其他位置,但最后一个元素除外。

控制台日志显示如下垃圾值:

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

无论您从矢量中的哪个位置擦除,您的程序都有未定义的行为。 正如文档所说,该功能:

使擦除点处或擦除点之后的迭代器和引用无效,包括 end() 迭代器。

所以,你的迭代器在你擦除的那一刻就死了。 这就是为什么该函数返回一个新的迭代器(返回到现在位于您刚刚删除的位置的项目)的原因。 您必须更新循环的迭代器才能使用它。

从循环中的标准容器中擦除的惯用方法是将迭代器步进循环体本身:

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

但是,这通常不是从矢量中删除项目的好方法。 如果向量包含很多要删除的值怎么办? 您的操作变得非常低效,因为每次擦除都必须打乱向量中的剩余项目。

所以更好的方法是erase-remove 习惯用法

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

从 C++20 开始,这进一步简化了

std::erase(v, 7);

暂无
暂无

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

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