C++primer-learning-notes-chapter9

236 阅读21分钟

顺序容器

  • 为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。

顺序容器类型

vector	//可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。
deque	//双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。
list	//双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
forward_list	//单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。
array	//固定大小数组。支持快速随机访问。不能添加或者删除元素。
string	//与vector相似的容器,但专门用于保存字符。随机访问块。在尾部插入/删除速度快。
  • 除了固定大小的array外,其他容器都提供高效、灵活的内存管理。
  • forward_list和array是新C++标准增加的类型。
  • string vector将元素保存在连续的内存空间中。添加元素有时可能需要分配额外的存储空间。
  • list forward_list 额外内存开销很大
  • deque 支持快速的随机访问,中间添加或删除代价很高。两端速度与list,forward_list相当。
  • 只有输入时需要在容器中间位置插入元素,随后随机访问:确定是否需要再容器中间位置添加元素,vector追加数据,再sort重排,再追加。 或考虑输入阶段使用list,输入完成将list内容拷贝到一个vector中。
  • 不确定使用哪种容器,可以只是用vector,list,使用迭代器,不适用下标操作,避免随机访问。
list<Sales_data>
deque<double>
vector<vector<string>> lines;

容器操作

//类型别名
iterator	//此容器类型的迭代器类型
const_iterator	//可以读取元素但不能修改元素的迭代器类型
size_type	//无符号整数类型,足够保存此种容器类型最大可能的大小
difference_type	//带符号整数类型,足够保存两个迭代器之间的距离
value_type	//元素类型
reference	//元素的左值类型;和value_type &含义相同
const_reference	//元素的const左值类型,即const value_type &

list<string>::iterator iter;
vector<int>::difference_type count;
//构造函数
C c;	//默认构造函数,构造空容器
C c1(c2);或C c1 = c2;	//构造c2的拷贝c1
C c(b, e)	//构造c,将迭代器b和e指定范围内的所有元素拷贝到c
C c(a, b, c...)	//列表初始化c
C c(n)	//只支持顺序容器,且不包括array,包含n个元素,这些元素进行了值初始化
C c(n, t)	//包含n个初始值为t的元素

list<string> authors = {"milton","shake","austem"};
vector<const char*> articles = {"a","an","the"};
list<string> list2(authors);
deque<string> authList(authors);//错:容器类型不匹配
vector<string> words(articles);//容器类型不匹配

//可将const char*元素转换为string
forward_list<string> words(articles.begin(),articles.end());

vector<int> ivec(10,-1);
list<string> svec(10,"hi");
forward_list<int> ivec(10);
deque<string> svec(10);

//定义array时要指定元素类型和大小
array<int,42>
array<string,10>
array<int,10>::size_type i;

array<int,10> ia1;//10个默认初始化的int
array<int,10> ia2 = {0,1,2,3,4,5,6,7,8,9};
array<int,10> ia3 = {42}; //ia3[0]为42,剩余元素为0

//array对内置数组类型拷贝或对象赋值不限制
int digs[10] = {0,1,2,3,4,5,6,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具有固定大小。
  • 和其他容器不同,默认构造的array是非空的。
  • 直接复制:将一个容器复制给另一个容器时,类型必须匹配:容器类型和元素类型都必须相同。
  • 使用迭代器复制:不要求容器类型相同,容器内的元素类型也可以不同。
//赋值和swap
c1 = c2;	//将c1中的元素替换成c2中的元素
c1 = {a, b, c...}	//将c1中的元素替换成列表中的元素(不适用于array)
c1.swap(c2)	//交换c1和c2的元素
swap(c1, c2)	//等价于c1.swap(c2)
c.assign(b, e)	//将c中的元素替换成迭代器b和e表示范围中的元素,b和e不能指向c中的元素
c.assign(il)	//将c中的元素替换成初始化列表il中的元素
c.assign(n, r)	//将c中的元素替换为n个值是t的元素

array<int,10> a1 = {0,1,2,3,4,5,6,7,8,9};
array<int,10> a2 = {0};
a1 = a2;
a2 = {0}; //错误:不能将一个花括号列表赋予数组。

//关联容器,array类型不支持assign,也不允许用花括号包围的值列表进行赋值。

//使用assign
list<string> names;
vector<const char*> oldstyle;
names = oldstyle;//错误
names.assign(oldstyle.cbegin(),oldstyle.cend());

list<string> slist1(1);//1个元素
slist1.assign(10,"hiya");//10个元素。
//相当于 slist1.clear();   slist1.insert(slist1.begin(),10,"hiya");

//使用swap
vector<string> svec1(10);
vector<string> svec2(55);
swap(svec1,svec2);//元素本身未交换,只是交换了两个容器的内部数据结构。指向容器的迭代器,引用和指针不会失效
//string类型,swap后迭代器,引用和指针失效
//swap两个array会真正交换它们的元素。迭代器,引用和指针绑定的元素保持不变。
//大小
c.size()	//c中元素的数目(不支持forward_list)
c.max_size()	//c中可保存的最大元素数目
c.empty()	//若c中存储了元素,返回false,否则返回true
//添加元素
c.push_back(t)	//在c尾部创建一个值为t的元素,返回void
c.emplace_back(args)	//同上
c.push_front(t)	//在c头部创建一个值为t的元素,返回void
c.emplace_front(args)	//同上
c.insert(p, t)	//在迭代器p指向的元素之前创建一个值是t的元素,返回指向新元素的迭代器
c.emplace(p, args)	//同上
c.inset(p, n, t)	//在迭代器p指向的元素之前插入n个值为t的元素,返回指向第一个新元素的迭代器;如果n是0,则返回p
c.insert(p, b, e)	//将迭代器b和e范围内的元素,插入到p指向的元素之前;如果范围为空,则返回p
c.insert(p, il)	//il是一个花括号包围中的元素值列表,将其插入到p指向的元素之前;如果il是空,则返回p

//forward_list有自己专有版本的insert和emplace。forward_list不支持push_back和emplace_back。
//vector和string不支持push_front和emplace_front。
//当我们用一个对象去初始化容器或者将对象插入到容器时,实际上放入的是对象的拷贝。
//emplace开头的函数是新标准引入的,这些操作是构造而不是拷贝元素。
//传递给emplace的参数必须和元素类型的构造函数相匹配。
//向一个vector,string,deque插入元素会使所有指向容器的迭代器,引用和指针失效。
//使用push_back
string word;
while(cin>>word)
    container.push_back(word);  //可以是list,vector,deque

void pluralize(size_t cnt,string& word){
    if(cnt>1)
        word.push_back('s');  //string是一个字符容器
}

//push_front  list,forward_list,deque
list<int> ilist;
for(size_t ix=0;ix!=4;++ix)
    ilist.push_front(ix);
    
//特定位置添加元素
ilist.insert(iter,"hllo");//添加到iter之前的位置

vector<string> svec;
list<string> slist;
slist.insert(slist.begin(),"hello");//相当于slist.push_front("hello");

svec.insert(svec.begin(),"hello");//vector不支持push_front,但可以插入到begin()之前
//插入到vector末尾之外所有位置都可能很慢。

//插入范围内元素
svec.insert(svec.end(),19,"anna");

vector<stirng> v = {"","",""};
slist.insert(slist.begin(),v.end()-2,v.end());
slist.insert(slist.end(),{"","",""});

//使用insert的返回值
list<string> lst;
auto iter = lst.begin();
while(cin>>word)
    iter = lst.insert(iter,word);//等价于调用push_front
    
//使用emplace
//emplace_front,emplace,emplace_back //构造而不是拷贝元素。将参数传递给元素类型的构造函数。
//emplace成员使用这些参数在容器管理的内存空间中直接构造元素。
//对应push_front,insert,push_back
c.emplace_back("",23,4.4);  //c保存Sales_data元素
c.push_back("",33,44); //错误:没有接受三个参数的push_back版本。
c.push_back(Sales_data("",33,3));
//对emplace_back的调用和第二个push_back调用会创建新的Sales_data对象。在调用
//emplace_back时,会在容器管理的内存空间中直接创建对象,而调用push_back则会
//创建一个局部临时对象,并将其压入容器中。
c.emplace_back(); //使用Sales_data的默认构造函数
c.emplace(iter,"555");//使用Sales_data(string)
c.empace_front("33",4,3);
//获取迭代器
c.begin(), c.end()	//返回指向c的首元素和尾元素之后位置的迭代器
c.cbegin(), c.cend()	//返回const_iterator

list<string> a = {"","",""};
auto it1 = a.begin();
auto it2 = a.rbegin();
auto it3 = a.cbegin();
auto it4 = a.crbegin();//list<string>::const_reverse_iterator

list<string>::iterator it5 = a.begin();
list<string>::const_iterator it6 = a.begin();
auto it7 = a.begin();
auto it8 = a.cbegin();
//反向容器
reverse_iterator	//按逆序寻址元素的迭代器
const_reverse_iterator	//不能修改元素的逆序迭代器
c.rbegin(), c.rend()	//返回指向c的尾元素和首元素之前位置的迭代器
c.crbegin(), c.crend()	//返回const_reverse_iterator

访问元素

  • 包括array在内每个顺序容器都有一个front成员函数,除forward_list外所有顺序容器都有一个back成员函数。这两个操作分别返回首元素和尾元素的引用。
c.back()	//返回c中尾元素的引用。若c为空,函数行为未定义
c.front()	//返回c中头元素的引用。若c为空,函数行为未定义
c[n]	//返回c中下标是n的元素的引用,n时候一个无符号证书。若n>=c.size(),则函数行为未定义
c.at(n)	//返回下标为n的元素引用。如果下标越界,则抛出out_of_range异常

//at和下标操作只适用于string、vector、deque、array
//back不适用于forward_list。
//如果希望下标是合法的,可以使用at函数。
if(!c.empty()){
    auto val = *c.begin(),val2 = c.front(); //第一个元素的拷贝
    auto last = c.end()
    auto val3 = *(--last); //不能递减forward_list迭代器
    auto val4 = c.back();  //forward_list不支持 均为最后一个元素的拷贝
}
  • 访问成员函数返回的是引用(在容器中访问元素的成员函数,即front,back,at和下标,返回的都是引用)。若容器是const对象,返回值则为const引用。
if(!c.empty()){
    c.front() = 42;
    auto &v = c.back();
    v = 1024;
    auto v2 = c.back();
    v2 = 0;
}

//下标操作和安全的随机访问
vector<string> svec; //空vector
cout<<svec[0]; //运行时错误:svec中没有元素
cout<<svec.at(0); //抛出一个out_of_range异常

删除元素

c.pop_back()	//删除c中尾元素,若c为空,则函数行为未定义。函数返回void
c.pop_front()	//删除c中首元素,若c为空,则函数行为未定义。函数返回void
c.erase(p)	//删除迭代器p指向的元素,返回一个指向被删除元素之后的元素的迭代器,若p本身是尾后迭代器,则函数行为未定义
c.erase(b, e)	//删除迭代器b和e范围内的元素,返回指向最后一个被删元素之后元素的迭代器,若e本身就是尾后迭代器,则返回尾后迭代器
c.clear()	//删除c中所有元素,返回void
  • forward_list有特殊版本的erase
  • forward_list不支持pop_back
  • vector和string不支持pop_front
list<int> lst = {0,1,2,3,4,5,6,7,8,9};
auto it = lst.begin();
while(it!=lst.end())
    if(*it % 2)
        it = lst.erase(it);
    else:
        ++it;

slist.clear();
slist.erase(slist.begin(),slist.end());//等价调用

特殊的forward_list操作

  • 为了添加或删除一个元素,需要访问其前驱,以便改变前驱的链接,单向链表中没有简单的方法来获取一个元素的前驱,所以,要通过改变给定元素之后的元素来完成。
  • 删除elem3应用指向elem2的迭代器调用erase_after.
  • forward_list定义了before_begin,它返回一个首前迭代器,这个迭代器允许我们在链表首元素之前添加或删除元素。
lst.before_begin()	//返回指向链表首元素之前不存在的元素的迭代器,此迭代器不能解引用。
lst.cbefore_begin()	//同上,但是返回的是常量迭代器。
lst.insert_after(p, t)	//在迭代器p之后插入元素。t是一个对象
lst.insert_after(p, n, t)	//在迭代器p之后插入元素。t是一个对象,n是数量。若n是0则函数行为未定义
lst.insert_after(p, b, e)	//在迭代器p之后插入元素。由迭代器b和e指定范围。
lst.insert_after(p, il)	//在迭代器p之后插入元素。由il指定初始化列表。
emplace_after(p, args)	//使用args在p之后的位置,创建一个元素,返回一个指向这个新元素的迭代器。若p为尾后迭代器,则函数行为未定义。
lst.erase_after(p)	//删除p指向位置之后的元素,返回一个指向被删元素之后的元素的迭代器,若p指向lst的尾元素或者是一个尾后迭代器,则函数行为未定义。
lst.erase_after(b, e)	//类似上面,删除对象换成从b到e指定的范围。
  • 当在forward_list中添加或删除元素时,必须关注两个迭代器:一个指向我们要处理的元素,另一个指向其前驱。
forward_list<int> flst = {0,1,2,3,4,5,6,7,8,9};
auto prev = flst.before_begin();
auto curr = flst.begin();
while(curr != flst.end())
    if(*curr % 2)
        curr = flst.erase_after(prev);
    else
        prev = curr;
        ++curr;

改变容器的大小

c.resize(n)	//调整c的大小为n个元素,若n<c.size(),则多出的元素被丢弃。若必须添加新元素,对新元素进行值初始化
c.resize(n, t)	//调整c的大小为n个元素,任何新添加的元素都初始化为值t

list<int> ilist(10,42);
ilist.resize(15);多50
ilist.resize(25,-1);
ilist.resize(5);

容器操作可能使迭代器失效

  • 在向容器添加元素后:
    • 如果容器是vector或string,且存储空间被重新分配,则指向容器的迭代器、指针、引用都会失效。若存储空间未重新分配,指向插入位置前有效,后面无效。
    • 对于deque,插入到除首尾位置之外的任何位置都会导致指向容器的迭代器、指针、引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在元素的引用和指针不会失效。
    • 对于list和forward_list,指向容器的迭代器、指针和引用依然有效。
  • 在从一个容器中删除元素后:
    • 对于list和forward_list,指向容器其他位置的迭代器、引用和指针仍然有效。
    • 对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素外其他元素的迭代器、指针、引用都会失效;如果是删除deque的尾元素,则尾后迭代器会失效,但其他不受影响;如果删除的是deque的头元素,这些也不会受影响。
    • 对于vector和string,指向被删元素之前的迭代器、引用、指针仍然有效。
vector<int> vi = {0,1,2,3,4,5,6,7,8,9};
auto iter = vi.begin();
while(iter != vi.end()){
    if(*iter % 2){
        iter = vi.insert(iter,*iter); //返回新元素的迭代器
        iter += 2;
    }else{
        iter = vi.erase(iter);  //返回下一元素的迭代器
    }
}

//不要保存end返回的迭代器
auto begin = v.begin(),end = v.end(); //添加元素后end中的迭代器失效了,出现错误,不应保存。
while(begin!=end){
    ++begin;
    begin = v.insert(begin,42);
    ++begin;
}

//正确写法
while(begin!=v.end()){
    ++begin;
    auto begin = v.insert(begin,42);
    ++begin;
}

vector对象是如何增长的

  • vector和string在内存中是连续保存的,如果原先分配的内存位置已经使用完,则需要重新分配新空间,将已有元素从就位置移动到新空间中,然后添加新元素。再释放旧空间。很慢,所以通常会分配比新的空间需求更大的内存空间。容器预留这些控件作为备份,可用来保存更多的新元素。使用此策略后,其扩张操作通常比list和deque还要快。
c.shrink_to_fit()	//将capacity()减少到和size()相同大小
c.capacity()	//不重新分配内存空间的话,c可以保存多少个元素
c.reverse(n)	//分配至少能容纳n个元素的内存空间
//shrink_to_fit只适用于vector、string和deque
//capacity和reverse只适用于vector和string。
//reverse不改变容器中元素的数量,仅影响vector预先分配多大的内存空间。

capacity和size

vector<int> ivec; //size:0,capacity依赖具体实现
cout<<ivec.size()<<ivec.capacity()<<endl;
for(vector<int>::size_type ix = 0;ix!=24;++ix){
    ivec.push_back(ix);
}
cout<<ivec.size()<<ivec.capacity()<<endl;//size:24,capacity应大于等于24,依赖于标准库实现

ivec.reverse(50);//将capacity至少设定为50,可能会更大。
cout<<ivec.size()<<ivec.capacity()<<endl;

while(ivec.size() != ivec.capacity()){
    ivec.push_back(0);
}
cout<<ivec.size()<<ivec.capacity()<<endl; //50 50

//再添加一个新元素,vector就不得不重新分配空间
ivec.push_back(42);
cout<<ivec.size()<<ivec.capacity()<<endl; //51,capacity应大于等于51

//使用shrink_to_fit要求vector将超出当前大小的多余内存退回给系统
ivec.shrink_to_fit();
cout<<ivec.size()<<ivec.capacity()<<endl;//只是一个请求,标准库并不保证退还内存。

额外的string操作

构造string的其他方法

string s(cp, n)	//s是cp指向的数组中前n个字符的拷贝,此数组至少包含n个字符
string s(s2, pos2)	//s是string s2从下标pos2开始的字符的拷贝。若pos2 > s2.size(),则构造函数的行为未定义。
string s(s2, pos2, len2)	//s是string s2从下标pos2开始的len2个字符的拷贝。
const char* cp = "hello world!!!"; //以空字符结束的数组
char noNull[] = {'h','i'};
string s1(cp); //拷贝 直到遇到空字符
string s2(noNull,2); //s2 == "hi"
string s3(noNUll); //未定义:noNull不是以空字符结束
string s4(cp+6,5);//从cp[6]开始拷贝5个字符
string s5(s1,6,5); //从s1[6]开始拷贝5个字符
string s6(s1,6); //从s1[6]拷贝至末尾
string s7(s1,6,20);//同上
string s8(s1,16); //抛出out_of_range异常

substr操作

s.substr(pos, n)	//返回一个string,包含s中从pos开始的n个字符的拷贝。pos的默认值是0,n的默认值是s.size() - pos,即拷贝从pos开始的所有字符。

改变string的其他方法

s.insert(pos, args)	//在pos之前插入args指定的字符。pos可以使是下标或者迭代器。接受下标的版本返回指向s的引用;接受迭代器的版本返回指向第一个插入字符的迭代器。
s.erase(pos, len)	//删除从pos开始的len个字符,如果len被省略,则删除后面所有字符,返回指向s的引用。
s.assign(args)	//将s中的字符替换成args指定的字符。返回一个指向s的引用。
s.append(args)	//将args指定的字符追加到s,返回一个指向s的引用。
s.replace(range, args)	//删除s中范围range中的字符,替换成args指定的字符。返回一个指向s的引用。

string搜索操作

  • 每个搜索操作都返回一个string::size_type值,表示匹配发生位置的下标。如果搜索失败则返回一个名为string::npos的static成员(类型是string::size_type,初始化值是-1,也就是string最大的可能大小)。
s.find(args)	//查找s中args第一次出现的位置
s.rfind(args)	//查找s中args最后一次出现的位置
s.find_first_of(args)	//在s中查找args中任何一个字符第一次出现的位置
s.find_last_of(args)	//在s中查找args中任何一个字符最后一次出现的位置
s.find_first_not_of(args)	//在s中查找第一个不在args中的字符
s.find_first_not_of(args)	//在s中查找最后一个不在args中的字符

//args必须是一下的形式之一:
c, pos	//从s中位置pos开始查找字符c。pos默认是0
s2, pos	//从s中位置pos开始查找字符串s。pos默认是0
cp, pos	//从s中位置pos开始查找指针cp指向的以空字符结尾的C风格字符串。pos默认是0
cp, pos, n	//从s中位置pos开始查找指针cp指向的前n个字符。pos和n无默认值。

string::size_type pos = 0;
while((pos = name.find_first_of(numbers,pos)) != string::npos){
    cout<<pos<<name[pos]<<endl;
    ++pos;
}

compare函数

  • 逻辑类似于C标准库的strcmp函数,根据s是等于、大于还是小于参数指定的字符串,s.compare返回0、正数或负数。
s2	//比较s和s2
pos1, n1, s2	//比较s从pos1开始的n1个字符和s2
pos1, n1, s2, pos2, n2	//比较s从pos1开始的n1个字符和s2
cp	//比较s和cp指向的以空字符结尾的字符数组
pos1, n1, cp	//比较s从pos1开始的n1个字符和cp指向的以空字符结尾的字符数组
pos1, n1, cp, n2	//比较s从pos1开始的n1个字符和cp指向的地址开始n2个字符

数值转换

to_string(val)	//一组重载函数,返回数值val的string表示。val可以使任何算术类型。对每个浮点类型和int或更大的整型,都有相应版本的to_string()。和往常一样,小整型会被提升。
stoi(s, p, b)	//返回s起始子串(表示整数内容)的数值,p是s中第一个非数值字符的下标,默认是0,b是转换所用的基数。返回int
stol(s, p, b)	//返回long
stoul(s, p, b)	//返回unsigned long
stoll(s, p, b)	//返回long long
stoull(s, p, b)	//返回unsigned long long
stof(s, p)	//返回s起始子串(表示浮点数内容)的数值,p是s中第一个非数值字符的下标,默认是0。返回float
stod(s, p)	//返回double
stold(s, p)	//返回long double

容器适配器

  • 三个顺序容器适配器:stack,queue,priority_queue
  • 适配器是使一事物的行为类似于另一事物的行为的一种机制,例如stack可以使任何一种顺序容器以栈的方式工作。

适配器的通用操作和类型

size_type	//一种类型,须以保存当前类型的最大对象的大小
value_type	//元素类型
container_type	//实现适配器的底层容器类型
A a;	//创建一个名为a的空适配器
A a(c)	//创建一个名为a的适配器,带有容器c的一个拷贝
关系运算符	//每个适配器都支持所有关系运算符:==、!=、<、 <=、>、>=这些运算符返回底层容器的比较结果
a.empty()	//若a包含任何元素,返回false;否则返回true
a.size()	//返回a中的元素数目
swap(a, b)	//交换a和b的内容,a和b必须有相同类型,包括底层容器类型也必须相同
a.swap(b)	//同上

定义一个适配器

  • 每个适配器都定义两个构造函数:默认构造函数创建一个空对象,接受一个容器的构造函数拷贝该容器来初始化适配器。
deque<int> deq;
stack<int> stk(deq);//从deq拷贝元素到stk
  • 默认情况下,stack和queue是基于deque实现的,priority_queue是在vector之上实现的。
//在vector上实现的空栈
stack<string,vector<string>> str_stk;
//str_stk2在vector上实现,初始化时保存svec的拷贝
stack<string,vector<string>> str_stk2(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头文件中

stack<int> intStack;//空栈
for(size_t ix = 0;ix != 10;++ix){
    intStack.push(ix);
}
while(!intStack.empty()){
    int value = intStack.top();
    intStack.pop();
}
//栈默认基于deque实现,也可以在list或vector之上实现。
s.pop()	//删除栈顶元素,不返回。
s.push(item)	//创建一个新元素,压入栈顶,该元素通过拷贝或移动item而来
s.emplace(args)	//同上,但元素由args来构造。
s.top()	//返回栈顶元素,不删除。
//容器适配器只可以使用适配器操作,不能直接使用基于某个类型实现的那个类型上的操作。
//如不能在一个stack上调用push_back

队列适配器

  • queue和priority_queue适配器定义在queue头文件中。
//queue默认基于deque实现,priority_queue默认基于vector实现
//queue也可以用list或vector实现,priority_queue也可基于deque实现。

q.pop()	//删除队首元素,但不返回。
q.front()	//返回队首元素的值,不删除。
q.back()	//返回队尾元素的值,不删除。只适用于queue
q.top()	//返回具有最高优先级的元素值,不删除。
q.push(item)	//在队尾压入一个新元素。
q.emplace(args)	
  • 标准queue使用一种先进先出的存储和访问策略。
  • priority_queue允许我们为队列中的元素建立优先级。新加入的元素会排在所有优先级比它低的已有元素之前。标准库在元素类型上使用<运算符来确定相对优先级。