• STL教程5-STL基本概念及String和vector使用


    活动地址:毕业季·进击的技术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的指定范围的字符
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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 << "两个字符串不相等";
    
    • 1
    • 2
    • 3
    • 4

    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++;//那么肯定是又重新申请内存了,这里++
       }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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对象的某一段内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    下面是常用的将数组复制到vector中的方法
    在这里插入图片描述

    2)插入push_back和删除元素pop_back

    v.push_back(1); //尾插元素1
    v.pop_back(); //尾删元素
    
    • 1
    • 2

    3)swap交换两个容器的数据空间

    交换两组的数据空间实际上是将指针交换了,空间并没有变化

    vector<int> v1(10, 1);
    vector<int> v2(10, 2);
    v1.swap(v2); //交换v1,v2的数据空间
    
    • 1
    • 2
    • 3

    4)size()获取容器有效元素个数

    (注意和capacity的区别)

    cout << v.size() << endl; //获取当前容器中的有效元素个数
    
    • 1

    4)capacity()获取当前容器的最大容量

    容量和size可能不相等,当容器的容量不够时,它会申请更大的(不是+1个空间,避免重复复制)

    cout << v.capacity() << endl; //获取当前容器的最大容量
    
    • 1

    5)resize改变容器中的有效元素个数

    1、当所给值大于容器当前的size时,将size扩大到该值,扩大的元素为第二个所给值,若未给出,则默认为0。
     2、当所给值小于容器当前的size时,将size缩小到该值,超过范围的元素将被删除。
    但是注意resize缩小,并不会缩小容量
    如果想要收缩空间,可以使用

    vector<int>(v).swap(v);
    
    • 1

    为什么呢,vector(v)是初始化了一个匿名对象,初始化完成后通过swap交换空间,两个内存空间的指针发生了交换,然后匿名对象执行结束就会被销毁

    6)at和[]

    v.at(10);//越界会抛异常
    v[10];//越界不会有异常,直接结束程序
    
    • 1
    • 2

    7)front和back返回第一个和最后一个元素

    v.front();
    v.back();
    
    • 1
    • 2

    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
    
    • 1
    • 2
    • 3

    earse位置参数也只能是迭代器
    如果仅有一个参数,则只是删除指定位置的元素
    如果有两个参数,则是指定的范围

    v1.erase(v1.begin());
    v1.erase(v1.begin()+2);
    v1.erase(v1.begin(),v1.end());
    v1.clear(0;
    
    • 1
    • 2
    • 3
    • 4

    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改变容器中的有效元素个数,

  • 相关阅读:
    050、事务设计之Percolator事务模型
    go-协程调度学习笔记
    力扣十四题. 最长公共前缀
    【web-5】HTTP/HTTPS
    27.在springboot中使用thymeleaf的属性inline(text, javascript 和 none)
    如何快速给图标包命名
    基于PHP+MySQL汽车票订票系统的设计与实现(含论文)
    docker 部署tig监控服务
    【进击的JavaScript|高薪面试必看】JS基础-异步
    MATLAB使用OMP实现图像的压缩感知实例
  • 原文地址:https://blog.csdn.net/baidu_41553551/article/details/125450819