C++primer十万字笔记 第九章 顺序容器
顺序容器
容器就是特定类型对象的集合,顺序容器为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。标准库提供了三种容器类型。
顺序容器概述
标准库中的顺序容器:
vector | 可变大小数组,支持快速随机访问。在尾部之外的位置插入或者删除元素可能会很慢 |
---|---|
deque | 双端列表。支持快速随机访问。在头尾插入删除很快 |
list | 双向链表。只支持双向顺序访问。任意地方插入删除都很快 |
forward_list | 单向链表只支持单向顺序访问 |
array | 固定大小数组,支持快速随机访问。不能添加或者删除元素 |
string | 与vector类似的容器但是专门用来保存字符,随机访问快。尾部插入删除也快。 |
容器库概览
容器库的操作上形成了一种层次:某些操作是所有容器类型都提供的,但是每个容器也会有自己独特的一些操作。
一般来说容器定义在一个头文件中,文件名和类型名均先相同。并且容器都定义为模板类,,我们需要提供额外的信息来具体化构造这个类,对于大多数(非绝对 )我们需要提供元素类型信息。
顺序容器几乎可以保存任何类型的元素(包括容器)。但是有些没有默认初始化的需要手动提供一个初始化器。
vector <noDeafult> v1(10,init);//提供了元素初始化器
vector<noDefault> v2(10);//因为没有默认构造参数因此不能进行初始化
下表是容易的一些操作。
类型别名 | - |
---|---|
iterator | 此容器类型的迭代器类型 |
const_iterator | 可以读取元素但是不可以修改元素的迭代器类型 |
size_type | 无符号整数类型 足够保存这种容器类型最大可能大小 |
difference_type | 带符号整数类型,足够保存两个迭代器之间的距离 |
value_type | 元素类型 |
reference | 元素的左值类型,即value_type & |
const_reference | 元素的const左值类型 即const valuej_type & |
构造函数 | |
C c; | 默认构造函数,构造空容器 |
C c1(c2); | 构造c2的拷贝 |
C c(b,e); | 构造c,将迭代器b和e指定范围内的元素拷贝到c 注意:array不支持 |
C c{a,b,c,…} | 列表初始化c |
复制与swap | |
c1 = c2 | 将c1中的元素替换为c2中的元素 |
c1 = {a,b,c…} | 将c1中的元素替换为列表中的元素 (不适用于array) |
a.swap(b) | 交换a,b中的元素 |
swap(a,b) | 交换a,b中的元素 |
大小 | |
c.size() | 得到c中元素是数目(不支持forward_list) |
c.max_size() | c可保存最大元素数目 |
c.empty() | 若c中存储了元素,返回false否则true |
添加删除元素 | 注意:在不同容器中这些操作的接口都不一样 |
c.insert(args) | 将args中的元素拷贝进c |
c.emplace(inits) | 使用inits构造c中的一个元素 |
c.erase(args) | 删除args指定的元素 |
c.clear() | 删除c中的所有元素 |
关系运算符 | |
==,!= | 所有容器都支持相等(不等)运算符 |
获取迭代器 | |
c.begin(),c.end() | 返回指向c的首元素和尾元素之后位置的迭代器 |
c.cbegin(),c.cend() | 返回const_iterator |
反向容器的额外成员 | 不支持forward_list |
reverse_iterator | 按逆序寻址元素的迭代器 |
const_reverse_iterator | 不能修改元素的逆序迭代器 |
c.rbegin(),c.rend() | |
c.crbegin(),c.crend() |
迭代器
和容器一样,迭代器有公共的借口:如果一个迭代器提供某个操作,那么所有提供相同操作的对着操作的实现方式都是相同的。得到的迭代指针都可以进行自加自减等操作。
一个迭代器范围由一对迭代器表示。可以通过反复递增begin到达end。迭代器遵守左闭合的特征,因为这样可以有一些好的性质如:如果beign和end相等则范围为空;如果begin与end不等则范围起码包含一个元素并且begin指向第一个元素;可以对begin递增多次到达end。意味着我们可以安全的使用如下代码进行遍历:while(begin!=end){++begin;}
容器类型成员
每个容器都定义了多个类型,如size_type,iterator和const_iterator还有反向迭代器等等。我们可以通过作用域运算符定义并使用它们如:
list<string>::iterator iter; //由于是模板类仍需提供额外信息
vector<int>::difference_type count; //count是由vector<int>定义的一个difference_type类型
容器定义与初始化
每个容器都定义了一个默认构造函数。除array之外其他容易默认构造函数都会创建一个指定类型的空容器。
只有顺序容器的构造函数才接受大小参数。
将一个容器初始化为另外一个容器的拷贝方式有两种:可以直接拷贝整个容器,或者(array除外)拷贝一个由迭代器指定的元素范围。为了创建一个容器为另外一个容器的拷贝,当传递迭代器参数来拷贝一个范围时,就不要求容器类型是匹配的了,而且新元素和原容器中的内容也可能不同只需要将拷贝的元素转换过去就行了。
list <string> authors = {"a","b","wafa","fawf"};
vector<const char*> articles = {"a","an","the"};
//当一个容器初始化为另外一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同
list<string> list2(authors); //正确,容器类型匹配
deque<string> authList(authors); //错误,容器类型不匹配
vector<string> words(articles); //错误容器类型必须匹配
forward_list<string> words(articles.begin(),articles.end());//使用了迭代器不需要匹配
列表初始化
在标准中我们可以对一个容器进行列表初始化。
list<string> authors = {"Milton","Shakespeatre","Auten:"};
vector<cosnt char *> articles = {"a","an","the"}; //使用了赋值运算符进行了拷贝初始化
vector<const char*> articles{"a","an","the"}; //使用了构造初始化
与顺序容器大小相关的初始化
除了与关联容器相同的构造函数外,顺序容器(array除外)提供另外一种构造函数,接受一个容器大小和一个(可选的)元素初始值。如果不提供初始值标准库就会创建一个值初始化器。
vector<int> ivec(10,-1); //10个int元素
list<string> svec(10,"hi!"); //10个strings,每个初始化为"hi"
forward_list<int> ivec(10); //10个元素,每个初始化为0
deque<string> svec(10); //10个元素每个都是空string
//注意如果元素有一个默认构造函数,可以只提供一个容器大小参数,如果没有除了大小参数以外还需要提供一个显式的元素初始值。
标准库具有固定大小
与内置数组一样,标准库array的大小同样是类型的一部分,当定义一个array时,除了指定元素类型,还需要指定容器大小。
array<int,40> a; array<string,10> b;
可以看到需要指定大小和类型
由于大小时array的一部分,array不支持普通的容器构造函数。这些构造函数都会确定IG容器的大小,要么隐式的要么显式的。而允许用户向一个array构造函数传递大小参数,最好情况下也是多余的,而且容易出错。
array大小固定,所以一个默认构造的array是非空的,其包含了与其大小一样多的被默认初始化的元素。如果对其进行列表初始化那么需要初始值的数目<=array的大小,如果<array的大小如果元素类型是类类型,这个类需要有一个默认构造函数来让初始化正常进行。
array<int,10>ia1; //10个默认初始化的int
array<int,10>ia2 = {0,1,2,3,4,5,6,7,8,9} //列表初始化
array<int,10>ia3={2}; //第一个元素为2,其余都是默认值0
我们虽然不能对默认数组进行拷贝或者对象赋值的操作,但是array无此限制。
int digs[10] = {0,1,2,3,4,5,7,8,9,};
int cpy[10] = digs; //错误,内置数组不能进行拷贝或者赋值
array<int,10> digits = {0,1,2,3,4,5,6,7,8,9};
array<int,10> copy = digits; //正确,array类型的可以进行拷贝赋值,只要类型匹配(类型和数量都要匹配)就可
赋值与swap
赋值运算将左边容器的元素全部替换成右边容器的拷贝。
c1=c2;c1={a,b,c};} //=列表也是一种赋值,会执行拷贝操作
array在类型和数量大小相同的情况下可以赋值
array<int,10> a1 = {0,1,2,3,4,5,6,7,8,9};
array<int,10> a2 = {0};
a1=a2; //正确,可以赋值
array<int,10> copy = a1; //正确,array类型的可以进行拷贝赋值,只要类型匹配(类型和数量都要匹配)就可
a2={0}; //不可以,只能在定义的时候使用列表赋值 好像也可以,在vscode中通过了
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4AIJSi67-1641812089059)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210829220042986.png)]
使用assign
赋值运算符要求左右同样的类型,它将右边运算对象中所有元素拷贝到左边中。顺序容器(array除外)还定义了assign的成员允许从一个不同但是相容的类型赋值,或者从容器的一个子序列赋值。assign操作使用参数所指定的元素(的拷贝)替换左边容器中的所有元素。
list<string> names;
vector<const char*> oldstyle;
names = oldstyle; //错误容器类型不匹配
names.assign(oldstyle.cbegin(),oldstyle.cend()); //使用assign可以进行呢一次隐式转换
由于assign时元素的值被替换,因此使用assign时最好别传递自己这个对象产生的迭代器指针。
使用swap
swap操作交换两个相同类型容器的内容。调用swap之后两个容器内容元素将会交换,原理是元素内容不会交换只是会交换两个容器内部的内部数据结构。除了array外交换两个容器内容很快在常数级别完成。而swap会真正交换真正的元素。
元素不会移动(array元素会移动)表示:指向容器的迭代器指针引用在swap后都不会失效,除了string(string回将短的字符串放到栈,长的放到动态内存)其余的指针引用迭代器都不会失效。
容器大小操作
除了forwawrd_list外每个容器都有三个大小相关的操作,有成员函数size()返回数目,empyt()返回是否为空,max_size返回一个大雨或等于该类型容器能容纳的最大元素的值。forward_list支持max_size和empty不支持size。
关系运算符
每个容器类型都支持相等运算符(==和!=);除了无序关联容器外所有容器都支持运算符>,>=,<=,<。关系运算符左右两边的对象必须是相同类型的容器并保存相同类型的元素。即我们只能将一个vector与另一个vector比较。而不能将vector与另一个vector进行比较。
比较两个元素实际上是逐对元素的比较。相等需要数量和大小都相等。只有保存的元素支持关系运算符比较才能使用容器间的关系运算符比较。
顺序容器操作
顺序容器和关联容器不同在于两者组织元素的方式不同,数据结构不同。这些不同之处直接关系到元素如何存储访问添加和删除。
向顺序容器中添加元素
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvULWSSU-1641812089060)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830103241478.png)]
list<string> lst;
auto iter = lst.begin();
while (cin>>word)iter = lst.insert(iter,word); //等价于调用push_front 因为inset会返回指向插入元素的迭代器。
使用emplace操作
emplace_front、emplace和emplace_back这些成员函数只是构造而不是卡噢诶元素。这些操作分别对应push_front、insert和push_back。当我们调用emplace时将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造元素,这会加快效率。:
//在c的末尾构造一个Sales_data对象
c.emplace_back("979-0028",25,15.99);//正确,使用三个参数的Sales_data构造函数
c.push_back("979-0028",25,15.99); //错误没有接受三个参数的pushback版本
c.push_back(Sales_data("979-0028",25,15.99)); //正确使用临时对象传递给push_backc.emplace_back(); //使用Sales_data默认构造函数
c.emplace(iter,"9990-88"); //使用Sales_data(string)在迭代器前创建一个元素。
访问元素
包括array在内的每个顺序容器都有一个front函数,除了forwawrd_list之外的顺序容器都有一个back成员函数。这个两个操作分别返回首元素和微元素的引用。
if(!c.empty()){//val和val2是c中第一个元素值的拷贝auto val = *c.begin(),val2 = c.front();auto last = c.end(); //auto val3 = *(--last); //不能递减forward_list迭代器 //end迭代器指向尾后,因此需要递减一下得到指向尾后的元素auto val4 = c.back(); //forward_list不支持
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Pl3lBh5-1641812089060)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830115219765.png)]
访问成员函数返回的是引用
在成员中访问元素的成员函数(即front,back下标和at)返回的都是引用,如果容器是一个const对象,则返回值是const引用。如果容器不是const的则返回值是普通引用,可以用引用来改变元素的值。
if(!c.empty()){c.front = 42;auto &v = c.back();v = 1024;auto v2 = c.back();v2 = 0;
}
//和往常一样,如果我们使用auto变量来保存这些函数的值,并希望使用此变量来改变元素的值,记得使用引用 。
下标访问和成员随机访问
提供快速随机访问的容器(string,vecto,deque和array)也都提供下标运算符。并且使用下标运算符的错误是一种严重的程序错误。我们可以使用at成员函数它越界时会抛出一个out_of_range异常。
vetor<string> svec; //空vector
cout<<svec[0]; //运行时错误:svec中没有元素
cout<<svec.at(0); //跑出一个out_of_range异常
删除元素
非array容器有很多种删除元素的方式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jggNlHqs-1641812089060)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830132628319.png)]
特殊的forward_list操作
forward_list有特殊版本的添加和删除操作。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eO1pxWJE-1641812089061)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830134824585.png)]
改变容器大小
使用resize来改变容器大小。array不支持改变大小。如果当前大小大雨所要求的大小,容器后部的元素会被删除。如果小于新大小会将元素添加到容器后部:
list<int> ilist(10,42);
ilist.resize(15); //将5个使用默认构造函数的int型加入后面
ilsit.resize(25,-1); //将10个位-1的元素加到后面
ilist.resize(); //删除后面多余的元素,保留最前面的5个
容器操作可能使迭代器失效
- 乳沟容器迭代器是vector或者string,切存储空间被重新分配,指向容器的迭代器指针引用都会失效。如果存储空间为重新分配指向插入位置之前的元素的迭代器指针和引用仍然有效,但是指向插入位置之后的迭代器指针和引用都会失效。
- 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器指针和引用失效。
- 对于list和forward_list,指向容器的迭代器(包括尾喉迭代器和首前迭代器),指针和引用仍然有效。
当我们从一个容器中删除元素后,指向被删除元素的迭代器指针引用都会是下。当我们删除一个元素后:
- 对于list和forward_list指向容器其他位置的迭代器(包括尾后迭代器和首前迭代器)仍然有效
- 对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素外其他元素的迭代器引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器也会失效,但其他迭代器引用和指针不受影响,如果删除首元素,这些也不会受到影响。
- 对于vector和string,指向被删元素之前的迭代器引用和指针仍然有效。并且只要删除元素尾后迭代器就会失效。
最好在改变元素大小数量后重新定位迭代器。
编写改变容器的循环程序
增删vector,string或deque元素的循环程序都必须考虑迭代器引用和指针可能失效的问题。程序需要保证循环中及时更新迭代器引用或者指针。如果循环中调用的是inset或者erase那么更新迭代器很容易因为这些操作都返回迭代器。
推荐不保存end迭代器而是在需要的时候直接调用毕竟调用的成本一般较低。
vector<int> vi = {0,1,2,3,4,5};
auto iter = vi.begin();
while(iter!=vi.end()){ //这里会不停的调用end,保持更新,从而可以规避删除元素后尾后指针失效的问题if(*iter%2){iter = vi.insert(iter,*iter); //插入会返回插入元素的迭代器位置,然后加2就是跳过这个和原来的迭代器直接到达下一个迭代器ietr += 2;}else{ietr= vi.erase(iter); //erase会返回删除元素的后面元素}
}
一些容器的内存增长
为了支持快速访问,vector将元素连续存储在一块区域每个元素紧挨着另外的元素。通常情况下我们不必关心一个标准库类型如何实现而时使用即可。对于vector和string其部分接口涉及到了内存管理。vector和string的实现通常会分配比新的空间更大的空间,容器预留空间用来备用。
管理容量的成员函数
vector和string提供了一些成员函数如下
容器大小管理操作 |
---|
shrink_to_fit只适用于vector,string和deque |
capacity和reserve只适用于vector和string |
c.capacity(); 返回不重新分配内存c可以保存多少元素的数量 |
c.reverse(n); 分配至少能容器n个元素的内存空间,如果当前容器拥有的内存不够才会重新分配内存并分配至少和需求一样大的。 |
capacity和size不一样,capacity是在不分配你内存的情况下最多可以保存多少元素,size指的是已经保存的元素数量。
vector<int> ivec;
cout<<"ivecc:size"<<ivec.size()<<"capacity:"<<ivec.capacity()<<endl;
//像ivec中添加24个元素
for (vector<int>::size_type ix=0;ix!=24;++ix){ivec.push_back(ix);cout<<"ivecc:size"<<ivec.size()<<"capacity:"<<ivec.capacity()<<endl;
}
额外的string操作
除了顺序容器共同操作外,string提供了一些额外的操作。这些操作大部分是提供c风格字符串之间的相互转换,要么是增加了我们用下表替代迭代器的版本。标准库对于string定义了大量的函数。
构造string的一些其他方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wIJ3HvzK-1641812089061)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830142822645.png)]
看得出来这些构造函数都是接受一个string或者是const char*参数,还接受(可选的)指定拷贝多少个字符串的参数。当我们传递给他们的是一个string时还可以给定下标来指定从哪个元素开始拷贝。
const char* cp = "hello world!!!"; //以空字符结束的数组
char noNull[] = {'H','i'}; //不是以空字符结束
string s1(cp); //拷贝cp中的字符直到遇到空字符
string s2(noNull,2); //从noNull中拷贝两个空字符
string s3(noNull); //未定义,noNull不是以空字符结束
string s4(cp+6,5); //从cp[6]开始拷贝5个字符s4=="world"
string s5(s1,6,5); //从s1[6]开始拷贝5个字符s5="world"
string s6(s1,6); //从s1开始拷贝直到s1末尾"world!!!"
stirng s7(s1,6,20); //正确,只拷贝到s1末尾,s7=="world!!!"
string s8(s1,16); //抛出一个out_of_range异常
substr方法
s.substr(pos,n); 返回从pos开始的n个字符的子串拷贝,pos默认值为0,n的默认值为s.size()-pos,即拷贝全部字符
改变string的其他方法
string类型除了支持顺序容器的赋值以及assign、insert、erase操作还定义了额外的insert和erase版本。
除了接受迭代器的insert和erase版本外,string还提供了接受了下标的版本。下标指出了开始删除的位置或者是insert到给定值的位置:
s.insert(s.size(),5,'!'); //在s末尾插入5ge感叹号
s.erase(s.size()-5,5); //从s背后删除5个字符
标准库string类型还提供了接受c风格字符串数组的insert和assign的版本。例如我们可以将以空字符结尾的字符数组insert到或assign给一个string:
const char *p = "State,plum Buck";
s.assigen(cp,7); //s为"Stately"
s.insert(s.size(),cp+7); //s=="Stately,plump Buck" 这里cp+7指向的是','是因为之前已经复制了Stateely因此只要从 cp+7地址的地方开始即可s.insert(0,s2,0,s2.size()); //在s[0]开始之前插入【从s2的第0个开始到size()个字符】
string类定义了两个额外的成员函数:append和replace,这两个函数可以改变string的内容。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ThL63c7h-1641812089061)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830153147140.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2iP1SD7l-1641812089061)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830153249697.png)]
string的搜索函数
string提供了6个不同的搜索函数,每个函数都有4个重载版本。每个搜索函数都返回string::size_type值来指向匹配发生的下标。如果搜索失败则返回一个名为string::npos(string::size_type并且值为-1)的static成员。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jXKrJ0PV-1641812089061)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830153850745.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sYgLFP1u-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830153854810.png)]
compare函数
除了关系运算符外,还提供了compare函数。类似于strcmp根据s和另一个字符串的大小返回0,正数或者负数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FULt9zU8-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830155912629.png)]
数值转换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvNq1tjD-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830160059204.png)]
上面的函数中的to是一个分隔符。
容器适配器
除了顺序容器外,标准库还定义了三个顺序容器适配器:stake、queue和priority_queue。适配器是标准库中的一个通用概念。容器、迭代器和函数都有适配器。适配器是一种机制能够把一个事物的行为像是另外一种事物一样。一个容器适配器接受一种已有的容器类型,使其行为看上去像是另外一种事物一样。例如stake接受一个顺序容器(除array或forward_list)并使其操作起来像是一个stack一样,下表列出所有容器适配器接受的操作和类型。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jr0x46Ay-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830160817470.png)]
定义一个适配器
每个适配器都定义两种构造函数:1. 默认构造函数创建一个空对象 2.接受一个容器的构造函数拷贝该容器来初始化适配器.例如deq是一个deque我们可以用deq来初始化一个新的stack:stack<int> stk<deq>;//从deq拷贝元素到stk
默认情况下stack和queue是基于deque实现的。priority_queue实在vector上实现的。我们可以在创建一个适配器时将一个命名的顺序容器作为第二个类型参数,来重载默认容器类型。
stack<string,vector<string>> str_stk; //使用vector来实现栈
stack<string,vector<string>> str_stk2(svec);//初始化时保存svec的拷贝
对一个给定的适配器使用什么容器是有限制的,所有适配器都要求容器具有添加和删除元素的能力。因此适配器不能构造在array之上。类似的我们也不能用forward_list来构造适配器,因为所有适配器都需要容器具有添加删除以及访问尾元素的能力。stack只要求push_back,pop_back和back操作,因此可以使用除array和forward_list之外的任何容器来构造。queue适配器要求back,push_back,front和push_front因此可以构造与list或者deque之上。但不能基于vector构造。priority_queue除了front,push_back和pop_back操作上还要求随机访问能力,因此可以构建在vector和deque之上,但不能基于list构造。
栈适配器
stack类型定义在stack头文件中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GWdGhOoy-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830162300518.png)]
stack<int> intStack; //空栈
for(size_t ix=0;ix!=10;++ix)intStack.push(ix); //intStack保存0到9十个数
while (!instack.empty()){int value = intStack.top(); //栈道栈顶值intStack.pop(); //弹出栈顶值
}
队列适配器
queue和priority_queque适配器定义在queue头文件中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1eNNhGFy-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830163237076.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YWdSaIOx-1641812089062)(C:\Users\15401\AppData\Roaming\Typora\typora-user-images\image-20210830163242790.png)]
queue采用一种FIFO的存储和访问策略。priority_queue允许为队列中的元素建立优先级,新加入的元素会排在所有优先级比它第的已有元素之前。标准库在元素类型上使用<运算符来确定相对优先级。pop会删除队首 的元素。
C++primer十万字笔记 第九章 顺序容器相关推荐
- 《C++Primer》第九章-顺序容器-学习笔记(1)-顺序容器定义与操作
<C++Primer>第九章-顺序容器-学习笔记(1) 文章目录 <C++Primer>第九章-顺序容器-学习笔记(1) 摘要 顺序容器的定义 容器元素的初始化 将一个容器初始 ...
- 《C++ Primer中文版(第五版)》 第九章 顺序容器
<C++ Primer中文版(第五版)> 第九章 顺序容器 元素在顺序容器中的顺序与其加入容器时的位置相对应.关联容器中元素的位置由元素相关联的关键字值决定. 所有容器都共享公共的接口,不 ...
- C++primer十万字笔记 第十一章 关联容器
关联容器支持高效的关键字查找和访问,两个主要的关联容器是map和set.map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值表示与索引相关联的数据.set中每个元素只包含 ...
- C++primer第九章 顺序容器 9.6 容器适配器
9.6容器适配器 除了顺序容器外,标准库还定义了三个顺序容器适配器:stack.queue和priority_queue 适配器(adaptor)是标准库中的一个通用概念.容器.迭代器和函数<3 ...
- C++primer第九章 顺序容器 9.5 额外的string操作
除了顺序容器共同的操作之外,string类型还提供了一些额外的操作.这些操作中 的大部分要么是提供string类和C 风格字符数组之间的相互转换,要么是增加了允许我们用下标代替迭代器的版本. 标准库s ...
- C++primer第九章 顺序容器 9.3 顺序容器操作
9.3顺序容器操作 顺序容器和关联容器的不同之处在于两者组织元素的方式.这些不同之处直接关系到了元素如何存储.访问.添加以及删除.上一节介绍了所有容器都支持的操作(罗列于表9.2(第295页)).本章 ...
- C++primer第九章 顺序容器 9.1 顺序容器概述 9.2容器库概览
一个容器就是一些特定类型对象的集合.顺序容器(sequentialcontainer)为程序员提供了控制元素存储和访问顺序的能力.这种顺序不依赖于元素的值,而是与元素加入容器 时的位置相对应.与之相对 ...
- C++ Primer 第九章 顺序容器
由于书籍上写的已经很经典了,故大部分用图片的形式来阐述概念,代码纯手打进行验证. 1.顺序容器类型:vector.deque.list.forword_list.array.string. 2.顺序容 ...
- C++primer第九章 顺序容器 9.4 vector对象是如何增长的
为了支持快速随机访问,vector将元素连续存储,每个元素紧挨着前一个元素存储.通常情况下,我们不必关心一个标准库类型是如何实现的,而只需关心它如何使用.然而,对于vector和string,其部分实 ...
最新文章
- 设计模式之工厂模式和抽象工厂模式
- Exchange Server 2013之邮件存档配置
- android viewflipper图片轮播,使用ViewFlipper实现图片轮播
- 关于解决安装pwndbg问题sys.stderr.write(f“ERROR: {exc}“) /usr/bin/python3.5: No module named ensurepip
- altas(ajax)控件(二十三):等级选择控件Rating
- 如何跟面试公司谈论薪资?
- 去哪儿-10-city-ajax
- oracle数据库扩容方案_数据库一体机替代IOE架构,在财税行业的崛起
- Spring mvc介绍
- 5. 在Windows上安装Git
- SQL Server 2012笔记分享-10:理解数据压缩
- fisher criterion
- ssm+安卓APP校园学生疫情防范监控系统毕业设计源码281444
- 创新创业技术路线怎么写_2016如何撰写创新创业项目申请书.ppt
- antd-vue表格实现单击或者双击
- 详细解读TPH-YOLOv5 | 让目标检测任务中的小目标无处遁形
- java多线程技术体系
- 人工智能导论——概念篇
- 戴尔R710服务器配置raid阵列(附图文)
- 爬虫系列之豆瓣图书排行