从vector中删除最后一个元素会导致迭代问题



我的代码:

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

无论你从vector中的哪个位置擦除,程序都有未定义的行为。如文档所述,函数:

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

所以,在擦除的那一刻,迭代器就失效了。这就是为什么该函数返回一个新的迭代器(指向现在位于您刚刚删除的位置的项)。你必须更新循环的迭代器来使用它。

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

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

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

所以更好的方法是删除习惯用法:

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

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

std::erase(v, 7);

最新更新