创作初心:在加深个人对知识系统理解的同时希望可以帮助到更多需要的同学
😄柯一梦的专栏系列
🚀柯一梦的Gitee主页
🛠️柯一梦主页详情
座右铭:心向深耕,不问阶序;汗沃其根,花自满枝。

目录
1.initializer_list
编辑
2.emplace_back:
3.使用for循环打印多参数的自定义类型对象
3.1迭代器遍历v1
3.2for循环遍历
4.leetcode训练题,写一个杨辉三角
4.1使用C语言
4.2使用C++
5.迭代器失效
在今天vector的学习之前我们先讲解几个知识:
1.initializer_list

我们可以看到 c++11 里面vector的构造函数的一个参数是initializer_list,这个参数的作用是什么呢?
initializer_list是一个包装了“ 编译器 临时数组”的轻量级只读对象(这个对象里面有一些成员函数begin,end之类的,并且是用const修饰过了之后的),既然是“ 数组 ”,我们在初始化一些容器的时候就可以用{},传入多个值对容器进行初始化。它的底层原理是:在栈上开辟一个只读的空间,然后vector再主动的去读取initializer_list里面的内容,并且拷贝到自己的容器里。(注意:所以我们在使用{}初始化一个vector对象的时候,本质上就是直接初始化(这里又有小伙伴疑惑了,为什么这里不是隐式类型转换呢?其实如果我们的赋值方式是v{1,2,3},这里编译器会直接把{1,2,3}当成initializer去构造,但是如果是v={1,2,3},这里就涉及到了隐式类型转换,也就是先构造一个函数,然后再进行拷贝构造))
1 2 3 4 5 6 7 8 9
| int main() { vector<int> v1{ 1,2,3,4,5,6,7,8,9,10 }; for (const auto& e : v1) { cout << e << " "; } return 0; }
|
2.emplace_back:

emplace_back和push_back有什么区别呢?我们来看下面这段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| int main() { struct A { A(int a1,int a2) :_a1(a1) ,_a2(a2) { } A(const A& a) { } int _a1; int _a2; }; vector<A> v1; A a(1,2); v1.push_back(a); v1.push_back(A(1, 2)); v1.push_back({ 1,2 }); A a(1, 2); v1.emplace_back(a); v1.emplace_back(A(1, 2)); v1.emplace_back(1,2); return 0; }
|

3. 使用 for循环打印多参数的自定义类型对象
3.1迭代器遍历v1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| int main() { struct A { A(int a1, int a2) :_a1(a1) , _a2(a2) { } A(const A& a) :_a1(a._a1) , _a2(a._a2) { } int _a1; int _a2; }; vector<A> v1; A a1(1, 2); v1.push_back(a1); v1.push_back(A(1, 2)); v1.push_back({ 1,2 }); A a2(1, 2); v1.emplace_back(a2); v1.emplace_back(A(1, 2)); v1.emplace_back(1, 2); vector<A>::iterator it1 = v1.begin(); while(it1!=v1.end()) { cout << (*it1)._a1 << " " << (*it1)._a2 << endl; ++it1; } return 0; }
|
我刚才在写迭代器遍历v1的内容的时候出现了一些问题,我刚才写的是一个空的 构造函数 ,vector的push_back插入的是拷贝对象而不是对象本身,所以我们子啊使用push_back的时候要把自定义类型的拷贝构造先写好。
3.2for循环遍历
1 2 3 4 5 6 7 8 9 10 11
| for (const auto& aa : v1) { cout << aa._a1 << " " << aa._a2 << endl; }
for (auto [x, y] : v1) { cout << x << " " << y << endl; } return 0;
|

4.leetcode训练题,写一个杨辉三角
4.1使用C语言
先讲一下做题思路:我们要先构造出来一个二维数组,然后再去构造一维数组,紧接着就是给一维数组里面的各个地址 赋值 。在赋值的时候我们要先将每个一维数组的头尾进行赋值,然后再让每一行的元素=上一行该位置与前一个位置元素的和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int** generate(int numRows, int* returnSize, int** returnColumnSizes) { int** aa = (int**)malloc(sizeof(int*)*numRows); *returnColumnSizes = (int*)malloc(sizeof(int)*numRows); for(int i = 0;i<numRows;i++) { (*returnColumnSizes)[i] = i+1; aa[i] = (int*)malloc(sizeof(int)*(i+1)); } for(int i = 0;i<numRows;i++) { aa[i][0] = 1; aa[i][i] = 1; for(int j = 1;j<i;j++) { aa[i][j] = aa[i-1][j]+aa[i-1][j-1]; } } *returnSize = numRows; return aa; }
|
4.2使用C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Solution { public: vector<vector<int>> generate(int numRows) { vector<vector<int>> aa; aa.resize(numRows,vector<int>()); for(size_t num = 0;num<numRows;++num) { aa[num].resize(num+1,1); } for(size_t i = 2;i<aa.size();++i) { for(size_t j = 1;j<aa[i].size()-1;++j) { aa[i][j] = (aa[i-1][j])+(aa[i-1][j-1]); } } return aa; } };
|
5.迭代器失效
vector的 insert 和erase的使用都会牵扯到迭代器,这里面有一个隐形的炸弹就是迭代器失效
实例1:
insert:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<initializer_list> #include<iostream> #include<vector> #include<algorithm> void test2() { 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); vector<int>::iterator pos = find(v.begin(), v.end(), 2); v.insert(pos,10); v.erase(pos); for (auto& e : v) { cout << e << " "; } } int main() { test2(); return 0; }
|
这块代码会直接报错,因为vs2022编译器会直接终止这种违法行为。有的同学问为什么会违法呢?其实我们在insert的时候,v的空间可能会涉及到扩容的问题,一旦涉及扩容,先前指向的空间就会被释放,pos也就变成了野指针。
实例2
erase:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| #include<initializer_list> #include<iostream> #include<vector> #include<algorithm> void test2() { 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); v.push_back(8); v.push_back(9); v.push_back(10); vector<int>::iterator it = v.begin(); while (it != v.end()) { if ((*it) / 2 == 0) { v.erase(it); ++it; } } }
|
类似于insert,这个erase使用过的it迭代器依旧报错了
解决方法:我们再使用erase或者insert的时候,我们都要对迭代器进行重新赋值(erase和insert函数都有返回值,返回值就是迭代器)!!!