定义:一个容器就是一个特定类型对象的集合。
顺序容器概述
(1)顺序容器类型
vector:可变数组大小,支持快速访问
deque:双端队列,支持快速随机访问,在头尾位置插入/删除速度很快
forward_list:单向链表,只支持单向顺序访问。
array:固定大小数组,不能添加或删除元素
string:和vector类似,用来保存字符
容器库概览
迭代器
迭代器范围由一对迭代器表示,,通常被称为begin和end,而end从来都不会指向范围中的最后一个元素,而是指向尾元素之后的位置,其元素范围由数学表示为:
[begin,end)
容器定义和初始化
(1)将一个容器初始化为另一个容器的拷贝
可拷贝整个容器,也可以拷贝一个指定容器的元素范围
新容器和原容器的元素类型可以不同,只要能将要拷贝的元素转换为要初始化的元素的类型即可
list<string> authors={"nuktib","sha"m"aus"} vector<const char *> articles={"a","an","the"} list<string> list2(authors); //正确,类型匹配 deque<string> authlist(authors) //错误,容器类型不匹配 forward_list<string> words(articles.begin(),articles.end()) //上述正确,可以将const char*元素转换为string
(2)与顺序容器大小相关的构造函数
其中一个构造函数接收一个容器大小和一个元素初始值
list<string> i(10,"hi") //10个strings元素,每个都初始化为"hi" vector<int> v(10,-1) //10个int元素,每个都初始化为-1 deque<string> i(10) //10个元素,每个都是空的string
(3)标准库array具有固定大小
定义一个array时,除了指定元素类型,还要指定容器大小
array<int,42> array<string,10>
内置数组不支持拷贝或对象赋值操作,但array无此限制
int digs[10]={1,2,3} int cpy[10]=digs //错误,内置数组不支持拷贝和赋值 array<int,10> d={1,2,3,4,5,6,7} array<int,10> c=d //正确
赋值和swap
(1) assign赋值函数(仅顺序容器)
顺序容器定义了一个名为assign的成员,允许我们从一个不同但相容的类型赋值,或者从一个容器的子序列赋值。
例:
list<string> name; vector<const char*>old; name.assign(old.cbegin(),old.cend())
上述代码将name中的元素替换为迭代器指定范围中的元素的拷贝,assign的参数决定了容器中将有多少个元素以及他们的值是什么
(2)使用swap
swap操作交换两个相同类型容器的内容
vector<string> v1(10); vector<string> v2(20); 上述交换结束后,v1将会拥有20个元素,v2将会拥有10个元素
顺序容器操作
向顺序容器添加元素
(1)使用push_back
除了array和forward_list之外,每个顺序容器都支持push_back
(2)push_front
list,forward_list,deque容器还支持push_front将元素插入容器头部
list<int> l; for(int i=0;i!=4;i++) l.push_front(i)
(3)在特定位置添加元素
insert函数可在特定位置添加元素,每个insert元素都接受一个迭代器作为其第一个参数,insert函数将元素插入到迭代器所指得位置之前
虽然有些容器不支持push_front操作,但他们对于insert操作无此限制,因此可以将元素插入到容器开始的位置,不必担心容器是否支持push_front
insert另一个版本还接受一个元素数目和一个值,将指定数目的元素添加到指定位置之前。
s.insert(s.end(),10,"anna") //将10个元素插入到s的末尾
还可以接受一对迭代器或一个初始化列表插入
s.insert(s.end(),{"thses","as","sda","dasda"});
使用insert的返回值
list<string> l; auto iter = l.begin(); string word; while (cin >> word) iter = l.insert(iter, word);
上述代码实现在一个特定位置反复插入元素
第一次调用insert将刚刚读取的string插入到iter所指向的元素之前,insert返回的迭代器恰好指向这个新元素,我们将此迭代器赋予iter并重新开始循环,读取下一个单词,不断循环。
访问元素
所有顺序容器都存在一个front成员函数,,除了forward_list之外的所有顺序容器都由一个back成员函数,front成员函数返回首元素的引用,back成员函数返回尾元素的引用
可以通过该引用修改容器中元素的值
if(!c.empty()) { c.front()=42; auto &v=c.back() v=1024; }
删除元素
(1)pop_front和pop_back成员函数分别删除首元素和尾元素,vector和string,forward_list不支持上述操作
(2)earse
成员函数erase从容器指定位置删除元素,也可以删除迭代器指定的单个元素,也可以删除由一对迭代器指定的范围内的所有元素,上述最终均会返回指向删除的元素之后位置的迭代器。
例:删除所有的奇数
list<int> ls = { 0,1,2,3,4,5,6,7,8,9 }; auto it = ls.begin(); while (it != ls.end()) { if (*it % 2) it = ls.erase(it); else it++; }
接受一堆迭代器的erase版本允许我们删除一个范围内的元素:
例: s.erase(s.begin(),s.end())
特殊的forwa_list单向链表操作
单向链表中由于特殊的插入和删除,所以定义的函数也比较特殊
before_begin():返回指向链表首元素之前不存在的元素的迭代器,此迭代器不能解引用
insert_after(p,t):在迭代器p之后插入元素t
erase_after(p):删除p所指位置之后的元素
例:删除奇数元素:
forward_list<int> lst = { 0,1,2,3,4,5,6,7,8,9 }; auto pre = lst.before_begin(); auto cur = lst.begin(); while (cur != lst.end()) { if (*cur % 2) cur = lst.erase_after(pre); //将cur重置为erase_after的返回值,即指向cur的下一个元素 else { pre = cur; cur++; } }
改变容器大小
通过resize函数可以改变容器的大小,但array不支持此操作
c.resize(n):调整c为n个元素
c.resize(n,t):调整c为n个元素,任何新添加的元素都初始化为t
vector对象是如何增长的
为了支持随机访问,vector将元素连续存储,当不得不获取新的内存控件时,vector和string通常会分配比新的控件需求更大的内存控件,容器预留这些空间作为备用,可以保存更多元素。
capacity函数告诉我们容器在不扩张内存空间情况下可以容纳多少元素
size():是指目前已经保存的元素的数目
reverse(n):告诉容器至少分配容纳n给元素的空间
到此这篇关于c++ primer超详细讲解顺序容器的文章就介绍到这了,更多相关c++顺序容器内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!
需要了解更多c/c++开发分享C++ primer超详细讲解顺序容器,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/1111427.html