活动地址:毕业季·进击的技术er
夏日炎炎,热浪中我们迎来毕业季,这是告别,也是迈向新起点的开始,CSDN诚邀各毕业生/在校生/职场人讲述自己的毕业季故事,分享自己的经验,技术er的进击之路,等你来书写!你可以选择适合自己的对应身份从以下相关内容方向着笔,也可从自身经历出发,贴合活动主题参与投稿,文章题目自拟。
写作内容参考方向
提醒:在选择对应身份后,在发布作品前请把不用的内容(活动地址请保留)删掉
毕业生 | 在校生 | 职场人 |
---|---|---|
毕业后的去向:继续读研还是直接就业? | 目前是大几?学习的专业是?本专业让你Get到哪些新技能? | 目前为止毕业几年了?当初学习的是什么专业? |
大学4年,令你印象深刻的bug追查记 | 从哪个瞬间开始让你决定学习编程语言? | 是否从事了本专业工作?目前从事的行业、职业?入门的导师你还记得吗?为大家介绍一下吧 |
大学期间技术学习方面最有成就感的事? | 进入大学敲下的第一行代码是什么? | 从毕业生到职场IT人,最大的感受是? |
大学最遗憾的事/没有完成的事? | 目前学习中最大的收获/困难是? | 你觉得毕业季职场新人应如何选择工作? |
对于即将进入的行业,你有哪些期望? | 大学期间的学习目标是?对未来的职业规划是? | 工作中,技术er应如何在技术领域快速成长? |
毕业后的个人未来展望/未来规划? | 在技术学习过程中遇到的最大问题是?如何解决的? | 你用过哪些开源项目让你忍不住分享给朋友? |
如何看待毕业生面临的就业困境? | 目前参加了多少场编码大赛,获得了多少本证书?可以介绍一下吗? | 工作中用技术做过的最有成就感的事? |
… | 接下来的学习计划/实习计划? | 程序员三十五岁瓶颈你怎么看? |
… | … | 想对毕业生/在校生说的话? |
… | … | … |
提醒:在选择对应身份后,在发布作品前请把不用的内容(活动地址请保留)删掉
活动地址:毕业季·进击的技术er
一、STL基本概念
1、STL概述
STL(标准模板库),STL广义上分为:容器(container) 算法(algorithm) 迭代器(iterator),从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。
2、STL六大组件
容器(vector,list…)
算法(sort,find…)
迭代器(扮演容器算法之间的胶合剂,所有STL容器都有自己的专属迭代器)
仿函数(行为类似函数,可作为算法的某种策略)
适配器(一种用来修饰容器或者仿函数或迭代器接口的东西)
空间配置器(空间的配置与管理)
六大件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同策略的变化,适配器可以修饰仿函数。
下面开始介绍容器、算法和迭代器
在开发STL的时候,有一群人开发容器,有一群人开发算法,他们之间分工协作,但是如果各干各的,容器和算法可能就融合不到一起,这时候开发算法的人就对开发容器的人说,你们给我提供迭代器就好了,这样他们之间就能分工协作了,所以说迭代器是容器和算法的桥梁
3、容器
容器可以嵌套容器,它分为
- 序列式容器(排序,如Vector,List,Deque容器)容器中元素的位置是有顺序的,比如顺序表
- 关联式容器(元素在容器中并没有保存元素置入容器时的逻辑顺序)元素在容器中的位置是固定的,比如哈希表
4、迭代器
iterator模式定义:提供一种方法,使之能够依序访问某个容器所含的各个元素,而又无需暴露该容器内部展示方式。(迭代器可以理解为指针,对指针的操作基本都可以对迭代器操作,实际上,迭代器是一个类,这个类封装了一个指针)
4、算法
通过有限的步骤解决问题,什么查找,排序等等
STL提供了大约100个实现算法的模板函数
容器和算法接触的时候需要迭代器的帮助
5、迭代器基本语法
1、迭代器的声明
容器提供的迭代器 v.begin()返回开始的迭代器,但是由于容器存放的数据类型不一样,因此迭代器可能会有所差异,因此在定义一个迭代器对象的时候需要指明迭代器的类型,
比如容器是vector< int >a ;那么声明一个迭代器对象就是容器声明再加上迭代器,即
vvector< int >::iterator begin = c.begin();
2、迭代器的使用
迭代器对象可以认为是一个指针,容器存放的是什么数据,取出来时(*begin)就是什么数据类型,比如vector< Person >,想要访问Perons的age,是(*Person).age而不是(*Person)->age,因为存放的是Person,而不是Person *
嵌套打印
二、STL常用容器
1、string容器
1)string和char*的对比
- char * 是一个指针,String是一个类。string封装了char*,管理这个字符串,也就是string对象里面有个指针,是一个char*类型的容器
- Strig封装了很多实用的成员方法,比如查找,拷贝,删除,替换,插入
- 不需要考虑内存释放和越界。 string管理char*分配的内存,每一次string的复制取值都是由string类负责维护,不用担心复制越界和取值越界
2、String常用api
1)声明
string s=“aaaa”;
对于string,如果使用[]方式访问,出现越界将会直接挂掉不会抛异常,但是如果使用at方式,出现越界会向上抛出异常。
2)拼接+=
3)追加append
const char *s33="aaaaaaa";
s.append(s33);//全部追加char*
s.append(s33,2);//追加s2的前2个字符
string s44="aaaaaaa";
s.append(s44);//追加string类型
s.append(s44,0,4);//追加string的指定范围的字符
4)查找find
find是从前往后找,找第一次出现的位置,rfind是从后往前找。
第一个参数是目标,这个目标可以是char也可以是char*也可以是string,第二个参数是开始位置,第三个参数是终止位置
5)替换replace
第一个参数是起始位置,第二个参数是长度,第三个参数是替换成为的元素,可以是char*也可以是string。也就是前两个参数围成的区域会被割去换成第三个参数。注意第二个参数是长度
6)比较compare
(等于) = 返回 0
(大于) > 返回 1
(小于) < 返回 -1
string s1 = "abcd";
string s2 = "abcd2";
if (s1.compare(s2) == 0) cout << "两个字符串相等";
else cout << "两个字符串不相等";
7)截取字符串substr
两个参数为区间,第二个参数默认为最后
8)插入insert和删除erase
insert第一个参数是位置,第二个参数是插入的字符串,字符串可以是char*也可以是string
删除erase两个参数第一个是开始,第二个是删除的个数,第二个参数默认是最后
3、vector容器
vector< int>v;v是一个对象,v的地址是对象的地址,并不是第一个元素的地址,看第一个元素的地址应该是&(v[0])
1、vector是单口容器,是占得连续的内存空间
2、vector提供了两组迭代器,分别是v.begin()、v.end()指向了vector的第一个元素和最后元素的下一个位置,另外一组是v.rbegin()、v.rend(),分别指向了最后一个元素和第一个元素的前面的位置。
3、vector提供了push_back()从末尾插入元素,也提供了pop_back()弹出最后一个元素,建议使用这个,虽然也提供了insert在指定位置插入元素
4、对于string,如果使用[]方式访问,出现越界将会直接挂掉不会抛异常,但是如果使用at方式,出现越界会向上抛出异常,对于vector同样这样。
vector动态增长原理
当插入新元素时,如果空间不足,那么vector会重新申请更大的一块内存空间,将原空间数据拷贝到新空间,释放旧空间的数据,再把新元素插入新申请空间。
这里有个看申请了多少次空间的方法
int *address=NULL;
for(1-》1000000)//for循环这么多次 增加元素
if(address!=&(v[0])) //一个地址记录第一个元素的地址
{ address=&(v[0]);//如果发现第一个元素的地址发生变化
cout++;//那么肯定是又重新申请内存了,这里++
}
3、vector常用api
1)vector构造函数
1、拷贝构造函数
2、拷贝指定区间的元素
vector<int> v1; //构造int类型的空容器
vector<int> v2(10, 2); //构造含有10个2的int类型容器
vector<int> v3(v2); //拷贝构造int类型的v2容器的复制品
v3=v4;//因为有=的重载
vector<int> v4(v2.begin(), v2.end()); //使用迭代器拷贝构造v2容器的某一段内容
string s("hello world");
vector<char> v5(s.begin(), s.end()); //拷贝构造string对象的某一段内容
下面是常用的将数组复制到vector中的方法
2)插入push_back和删除元素pop_back
v.push_back(1); //尾插元素1
v.pop_back(); //尾删元素
3)swap交换两个容器的数据空间
交换两组的数据空间实际上是将指针交换了,空间并没有变化
vector<int> v1(10, 1);
vector<int> v2(10, 2);
v1.swap(v2); //交换v1,v2的数据空间
4)size()获取容器有效元素个数
(注意和capacity的区别)
cout << v.size() << endl; //获取当前容器中的有效元素个数
4)capacity()获取当前容器的最大容量
容量和size可能不相等,当容器的容量不够时,它会申请更大的(不是+1个空间,避免重复复制)
cout << v.capacity() << endl; //获取当前容器的最大容量
5)resize改变容器中的有效元素个数
1、当所给值大于容器当前的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为0。
2、当所给值小于容器当前的size时,将size缩小到该值,超过范围的元素将被删除。
但是注意resize缩小,并不会缩小容量
如果想要收缩空间,可以使用
vector<int>(v).swap(v);
为什么呢,vector(v)是初始化了一个匿名对象,初始化完成后通过swap交换空间,两个内存空间的指针发生了交换,然后匿名对象执行结束就会被销毁
6)at和[]
v.at(10);//越界会抛异常
v[10];//越界不会有异常,直接结束程序
7)front和back返回第一个和最后一个元素
v.front();
v.back();
8)insert插入元素和earse删除元素和clear清空vector
insert的位置参数只能是迭代器
vector支持随机访问,所以直接可以像下面这样直接+2
v1.insert(v1.begin(),10);//再开始位置插入10
v1.insert(v1.end(),10);//在结束位置插上10
v1.insert(v1.begin()+1,10);//在下标为1的位置插上10
earse位置参数也只能是迭代器
如果仅有一个参数,则只是删除指定位置的元素
如果有两个参数,则是指定的范围
v1.erase(v1.begin());
v1.erase(v1.begin()+2);
v1.erase(v1.begin(),v1.end());
v1.clear(0;
9)reserve和resize的区别
通过reserse函数改变容器的最大容量,resize函数改变容器中的有效元素个数。
reserve规则:
1、当所给值大于容器当前的capacity时,将capacity扩大到该值。
2、当所给值小于容器当前的capacity时,什么也不做。
resize规则:
1、当所给值大于容器当前的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为0。
2、当所给值小于容器当前的size时,将size缩小到该值。
三、总结
1、STL是一些“容器”的集合,STL也是算法和其他一些组件的集合。STL的容器和算法的桥梁是迭代器
2、定义的string是一个对象,里面封装了char指针,也封装了很多方法,且不需要考虑内存释放和回收
3、不管是string还是vector,使用[]越界会挂掉,使用at()会抛出异常
4、string可以拼接string char char类型数据
5、string +=拼接 append追加 find查找 replace代替 compare比较 截取字符串substr 插入insert和删除erase
6、vector< int>v;v是一个对象,v的地址是对象的地址,第一个元素的地址应该是&(v[0])
7、vector构造函数,有个按arr[]构造的方法 vector< int >v2(arr.begin(),arr.end()) 其它的构造v3=v4;vector v3(v2);vector v4(v2.begin(), v2.end());vector v2(10, 2);10个2
8、vector的常用函数插入push_back和删除元素pop_back,v1.swap(v2); //交换v1,v2的数据空间,size()获取容器有效元素个数,capacity()获取当前容器的最大容量,resize改变容器中的有效元素个数,