适合人群 如果你想要快速上手使用vector接口,将常用接口看完并且全部试验一遍即可。 如果想要了解迭代器失效的概念,可以试验一下最后两个小案例。
1、认识vector
1.1.vector简介
- vector是向量类型,可以容纳许多类型的数据,因此也被称为容器
- 可以理解为动态数组,是封装好了的类
- 进行vector操作前应添加头文件
#include<vector>
这只是vector的剪短介绍,如果还想深入了解vector的小伙伴可以参考vector官方文档。
2、vector的常用接口
2.1.一维vector初始化
方式1:
vector<int> v(5);
方式2.
vector<int> v(5, 1);
方式3.
vector<int> v1(v2);
方式4.
vector<int> v1(v2.begin(), v2.end());
vector<int> v1(v2.begin(), v2.begin()+5);
方式5.
int arr[5] = {1, 2, 3, 4, 5};
vector<int> v(arr, arr + 5);
2.2.二维vector初始化
vector<vector<int>> v;
vector<vector<int>> v(10)
vector<vector<int>> v(10, vector<int>(20, 1));
2.3.对vector进行操作(举例说明)
头文件
// 假设已经定义好了两个向量
#include <vector>
vector<int> v1, v2;
增
v1.assign(v2.begin(), v2.end());
v1.assign(10, 5);
v1.push_back(10);
v1.emplace_back(10);
v1.emplace(v1.begin() + 1, 10);
v1.insert(v1.begin() + 1, 3);
v1.insert(v1.begin() + 1, 10, 3);
v1.insert(v1.begin() + 1, v2.begin() + 5, v2.begin() + 10);
删
v1.pop_back();
v1.erase(v1.begin() + 2);
v1.erase(v1.begin() + 1, v1.begin() + 5);
v1.clear();
查
v1[i];
v1.at(i)
v1.front();
v1.back();
v1.size();
v1.capacity();
v1.empty();
改
v1.resize(10);
v1.resize(10, 2);
v1.reverse(100);
v1.swap(v2);
3、访问vector的几种方式
3.1.对向量添加元素
1.向向量中添加元素
vector<int> v;
for (int i = 0; i < 10; i ++) {
v.push_back(i);
}
2.从数组中选取数字添加到向量中
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int> v;
for (int i = 5; i < 10; i ++) {
v.push_back(a[i]);
}
3.从一个向量中选取元素添加到另一个向量中
vector<int> v1 = {1, 2, 3, 4, 5};
vector<int> v2;
for (vector<int>::iterator it = v1.begin(); it != v1.end(); it ++) {
v2.push_back(*it);
}
4.错误的添加方式
vector<int> v;
for (int i = 0; i < 10; i ++) {
v[i] = i;
}
3.2.从向量中读取元素
1.通过下标获取元素
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < v.size(); i ++) {
cout << v[i] << ' ';
}
2.通过迭代器获取元素
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (vector<int>::iterator it = v.begin(); it != v.end(); it ++) {
cout << *it << ' ';
}
3.范围for遍历元素
vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int num : v) {
cout << num << ' ';
}
4、常用的几种配合vector的算法
#inlude <algorithm>
sort(v.begin(), v.end();
find(v.begin(), v.end(), 2);
reverse(v.begin(), v.end());
max(v[0], v[1]);
min(v[0], v[1]);
5、迭代器失效
先将结论在举例子。
迭代器失效两种情况: 1.迭代器iterator所指向的空间已经被释放,对于vector这样的序列容器来说,此时iterator已经是野指针了。 2.迭代器iterator的代表的意义改变了。
如果你不懂上面的两种情况也没事,在看完下面的例子时候,再回头看一遍就懂了。
1.iterator变成"野指针"
vector<int> v = { 1, 2, 3, 4, 5 };
vector<int>::iterator it = v.begin();
cout << *it << endl;
v.reserve(10);
cout << *it << endl;
因为it = v.begin() ,所以当*it 的时候,输出的应该是1。但是在扩容之后,*it 就不能再输出了。这就是迭代器失效导致的。 解释:我们要有一个前置只是就是在vector 扩容的时候,并不是直接在容器的后面再开一段连续的空间,而是先拷贝一份更大的空间,然后讲原空间的vector中的元素一个一个的拷贝到先开的空间当中,最后释放掉原空间。虽然空间的数值都被拷贝到新空间中,但是原来的迭代器还在指向原有空间的开头位置,这就是迭代器失效。  所以只要当vector发生扩容的时候就会发生这种迭代器失效,所以平时使用insert 和push_back() 的时候都要小心。
2.iterator的意义改变了
vector<int> v = { 2, 4, 5 };
vector<int>::iterator it = v.begin();
while (it != v.end()) {
if (*it % 2 == 0) v.erase(it);
it++;
}
for (int i = 0; i < v.size(); i++) {
cout << v[i] << ' ';
}
为什么输出了4和5呢?(在Linux平台上输出4,5,在vs平台上直接程序崩溃)。 解释:因为2是偶数,所以一上来就要erase掉2,然后iterator往后走一步指向4。等等在这一步的时候就已经错了,iterator不指向4,而是指向5。???为什么呢?因为vector是序列式容器,在erase之后所有在iterator之后的元素都会往前移动一位,这样覆盖掉了原来iterator指向的位置了  所以,如果要改正这个错误的话,就要保证当删除元素的时候,迭代器it就不能往后走了,只有当没有删除元素的时候,迭代器才可以往后走。
vector<int> v = { 2, 4, 5 };
vector<int>::iterator it = v.begin();
while (it != v.end()) {
if (*it % 2 == 0) it = v.erase(it);
else it++;
}
for (int i = 0; i < v.size(); i++) {
cout << v[i] << ' ';
}
在erase数值之后,我们以为迭代器指向的位置,却不是它的位置,这种就是迭代器的意义改变了。也就是第二中迭代器失效。
总结:迭代器失效的两种情况 1.当insert或者erase的时候,因为iterator不会随着指向元素的改变(增加或者删除)而改变,单只iterator的意义发生改变。 2.当insert或者erase的时候,导致容器扩容或者缩容时,iterator变成了"野指针"。
|