全国工程建设行业优秀网站,wordpress可爱主题,山东网站建设seo,北京seo优化费用vector迭代器的失效问题
接上篇vector的介绍和使用中最后提到的vector迭代器#xff0c;我们继续来看vector迭代器的失效问题。 以下代码的功能是删除vector中所有的偶数#xff0c;请问那个代码是正确的#xff0c;为什么#xff1f; #include iostream
using na…vector迭代器的失效问题
接上篇vector的介绍和使用中最后提到的vector迭代器我们继续来看vector迭代器的失效问题。 以下代码的功能是删除vector中所有的偶数请问那个代码是正确的为什么 #include iostream
using namespace std;
#include vector
//第一种方法
int main()
{vectorint v{ 1, 2, 3, 4 };auto it v.begin();while (it ! v.end()){if (*it % 2 0)v.erase(it);it;}return 0;
}
//第二种方法
int main()
{vectorint v{ 1, 2, 3, 4 };auto it v.begin();while (it ! v.end()){if (*it % 2 0)it v.erase(it);elseit;}return 0;
} 答案是第二种第一种的方法会导致迭代器失效因为每删除一个erase迭代器后就不让使用了而第二种方法在 it v.erase(it)中解决了因为erase函数会返回删除元素的下一个位置的迭代器解决乐迭代器失效的问题。
Linux下g编译器对迭代器失效的检测 Linux下g编译器对迭代器失效的检测并不是非常严格处理也没有vs下极端。以下三种情况可以让我们对Linux下g迭代器失效情况更加了解 // 1. 扩容之后迭代器已经失效了程序虽然可以运行但是运行结果已经不对了
int main()
{vectorint v{1,2,3,4,5};for(size_t i 0; i v.size(); i)cout v[i] ;cout endl;auto it v.begin();cout 扩容之前vector的容量为: v.capacity() endl;// 通过reserve将底层空间设置为100目的是为了让vector的迭代器失效 v.reserve(100);cout 扩容之后vector的容量为: v.capacity() endl;// 经过上述reserve之后it迭代器肯定会失效在vs下程序就直接崩溃了但是linux下不会// 虽然可能运行但是输出的结果是不对的while(it ! v.end()){cout *it ;it;}cout endl;return 0;
}
程序输出
1 2 3 4 5
扩容之前vector的容量为: 5
扩容之后vector的容量为: 100
0 2 3 4 5 409 1 2 3 4 5 // 2. erase删除任意位置代码后linux下迭代器并没有失效
// 因为空间还是原来的空间后序元素往前搬移了it的位置还是有效的
#include vector
#include algorithm
int main()
{vectorint v{1,2,3,4,5};vectorint::iterator it find(v.begin(), v.end(), 3);v.erase(it);cout *it endl;while(it ! v.end()){cout *it ;it;}cout endl;return 0;
}程序可以正常运行并打印
4
4 5 // 3: erase删除的迭代器如果是最后一个元素删除之后it已经超过end
// 此时迭代器是无效的it导致程序崩溃
int main()
{vectorint v{1,2,3,4,5};// vectorint v{1,2,3,4,5,6};auto it v.begin();while(it ! v.end()){if(*it % 2 0)v.erase(it);it;}for(auto e : v)cout e ;cout endl;return 0;
}
// 使用第一组数据时程序可以运行
[slyVM-0-3-centos 20220114]$ g testVector.cpp -stdc11
[slyVM-0-3-centos 20220114]$ ./a.out
1 3 5// 使用第二组数据时程序最终会崩溃
[slyVM-0-3-centos 20220114]$ vim testVector.cpp
[slyVM-0-3-centos 20220114]$ g testVector.cpp -stdc11
[slyVM-0-3-centos 20220114]$ ./a.out
Segmentation fault 从上述三个例子中可以看到SGI STL中迭代器失效后代码并不一定会崩溃但是运行结果肯定不对如果it不在begin和end范围内肯定会崩溃的。 与vector类似string在插入扩容操作erase之后迭代器也会失效 #include string
void TestString()
{string s(hello);auto it s.begin();// 放开之后代码会崩溃因为resize到20会string会进行扩容// 扩容之后it指向之前旧空间已经被释放了该迭代器就失效了// 后序打印时再访问it指向的空间程序就会崩溃//s.resize(20, !);while (it ! s.end()){cout *it;it;}cout endl;it s.begin();while (it ! s.end()){it s.erase(it);// 按照下面方式写运行时程序会崩溃因为erase(it)之后// it位置的迭代器就失效了// s.erase(it); it;}
} 迭代器失效解决办法在使用前对迭代器重新赋值即可。 vector常见oj题 1.只出现一次的数字 - 力扣 class Solution {
public:int singleNumber(vectorint nums) {int value 0;for(auto e : nums){value ^ e;}return value;}
};
2.杨辉三角- 力扣LeetCode class Solution {
public:vectorvectorint generate(int numRows) {vectorvectorint vv;vv.resize(numRows);for(size_t i0;inumRows;i){vv[i].resize(i1,0);vv[i][0]vv[i][vv[i].size()-1]1;}if(numRows2)return vv;for(size_t i 2;inumRows;i){for(size_t j1;ji;j){vv[i][j]vv[i-1][j-1]vv[i-1][j];}}return vv;}
}; 总结通过上面的练习我们发现vector常用的接口更多是插入和遍历。遍历更喜欢用数组operator[i]的形式访问因为这样便捷。