STL中vector迭代器失效常见错误写法示例
最近在看STL容器失效的例子,涉及到vector数组迭代器失效的问题,如果不注意使用,很容易出现问题,我们先来看一下一个简单的示例程序,在数组nums中删除大于50的元素,代码如下:
代码语言:javascript复制#include <vector>
#include <iostream>
int main()
{
std::vector<int> nums = { 15, 25, 8, 45, 78, 90, 125 };
for (auto iter = nums.begin(); iter != nums.end();) {
if (*iter > 50) {
nums.erase(iter); // 此处在删除iter之后iter迭代器失效,再在后续的for循环中使用iter时会导致崩溃
} else {
iter ;
}
}
for (auto num : nums) {
std::cout << num << std::endl;
}
std::cin.get();
return 0;
}
在Visual Studio中运行上述程序后,会导致程序崩溃,截图如下:
错误为:vector iterators incompatible
,即向量迭代器不兼容
,
下面我们来看一下崩溃时的堆栈:
正确的用法
首先我们来看一下正确的写法,代码如下:
代码语言:javascript复制#include <vector>
#include <iostream>
int main()
{
std::vector<int> nums = { 15, 25, 8, 45, 78, 90, 125 };
for (auto iter = nums.begin(); iter != nums.end();) {
if (*iter > 50) {
//nums.erase(iter); // 此处在删除iter之后iter迭代器失效,再在后续的for循环中使用iter时会导致崩溃
iter = nums.erase(iter);
} else {
iter ;
}
}
for (auto num : nums) {
std::cout << num << std::endl;
}
std::cin.get();
return 0;
}
程序运行结果如下:
可以看到将之前代码的第9行的nums.erase(iter);
语句改成iter = nums.erase(iter);
就能正常删除vector数组中大于50的数了。这是因为vector数组在对某个iter迭代器执行erase操作之后会返回一个后向迭代器。而且vector是顺序容器,直接对nums.erase(iter)操作之后,iter本身以及其后的元素都会挪动位置了。但是nums.erase(iter)会返回一个正确的后序迭代器,将其赋值给iter,再对iter进行操作就OK了。