C++ Primer学习——顺序容器

1.顺序容器类型:
vector:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。连续存储容器。
deque:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。连续存储容器。
list:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
forward_list:单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。
array:固定大小数组。支持快速随机访问。不能添加或删除元素。
string:与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快。连续存储。

2.选择容器的一些基本原则:
① 除非你有很好的理由选择其他容器,否则应使用vector。
② 如果你的程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list。
如果程序要求随机访问元素,应使用vector或deque。
如果程序要求在容器的中间插入或删除元素,应使用list或forward_list。
如果程序需要在头尾位置插入或删除元素,但不会在中间位置进行插入或删除操作,则应使用deque。
⑥ 如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素,则
——首先,确定是否真的需要在容器中间位置添加元素。在处理输入数据时,通常可以很容易地向vector追加数据,然后再调用标准库的sort函数来重排容器中的元素,从而避免在中间位置添加元素。
——如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。

3.迭代器范围(iterator):由一对迭代器来表示。begin和end分别指向同一个容器中的第一个元素或者是尾元素之后的位置,范围为左闭合区间:[begin,end)。

4.每个容器类型都定义了一个默认构造函数。除array之外,其他容器的默认构造函数都会创建一个指定类型的空容器,且都可以接受指定容器大小和元素初始值的参数。
只有顺序容器的构造函数才接受大小参数,关联容器不支持。

5.容器赋值运算:
这里写图片描述

6.比较两个容器实际上是进行元素的逐对比较。

7.顺序容器特有的操作:
① 添加元素:
这里写图片描述
向一个vector或string添加元素可能引起整个对象存储空间的重新分配,重新分配一个对象的存储空间需要分配新的内存,并将元素从旧的空间移动到新的空间中。
除了array和forward_list之外,每个顺序容器都支持push_back。由于string是一个字符容器,用push_back在string末尾添加的是字符。
list、forward_list和deque容器还支持push_front。

//使用insert
vector<string> svec;
auto iter=svec.begin();
while(cin>>word)
   iter=svec.insert(iter,word); //vector不支持push_front,但是可以插入到begin()之前,但耗时长
                                //利用insert的返回值,可以在容器的特定位置反复插入元素

调用push或insert成员函数时,是将元素类型的对象传递给它们,这些对象被拷贝到容器中。而调用emplace成员函数时,是将参数传递给元素类型的构造函数,这些参数直接在容器管理的内存空间中构造元素,传递给emplace函数的参数必须与元素类型的构造函数相匹配。
② 访问元素:
这里写图片描述
在容器中访问元素的成员函数返回的都是引用。使用auto变量来保存这些函数的返回值,并且希望使用此变量来改变元素的值,必须将变量定义为引用。
③ 删除元素:
这里写图片描述
④ 特殊的forward_list操作:
forward_list是一个单向链表,添加或删除一个元素会改变序列中的链接。
这里写图片描述
⑤ 改变容器的大小:
用resize来增大或缩小容器,array不支持resize。
这里写图片描述
⑥ 容器操作可能使迭代器失效:
向容器添加元素后:
- 如果容器是vector或string,且存储空间被重新分配,则指向容器的迭代器、指针和引用都会失效。如果存储空间未重新分配,指向插入位置之前的元素的迭代器、指针和引用仍有效,但指向插入位置之后元素的迭代器、指针和引用将会失效。
- 对于deque,插入到除首尾位置之外的任何位置都会导致迭代器、指针和引用失效。如果在首尾位置添加元素,迭代器会失效,但指向存在的元素的引用和指针不会失效。
- 对于list和forward_list,指向容器的迭代器(包括尾后迭代器和首前迭代器)、指针和引用仍有效。

当我们删除一个元素后:
- 对于list和forward_list,指向容器其他位置的迭代器(包括尾后迭代器和首前迭代器)、指针和引用仍有效。
- 对于deque,如果在首尾之外的任何位置删除元素,那么指向被删除元素外其他元素的迭代器、引用和指针也会失效。如果是删除deque的尾元素,则尾后迭代器也会失效,但其他迭代器、引用和指针不受影响;如果删除首元素,这些也不会受影响。
- 对于vector和string,指向被删元素之前元素的迭代器、引用和指针仍有效。
注意:当我们删除元素时,尾后迭代器总是会失效。

8.容器容量大小管理(vector、string和deque):
c.capacity() 告诉我们容器在不分配新的内存空间的前提下容器最多可以保存多少元素。
c.reserve(n) 允许我们通知容器需要分配至少能容纳n个元素的内存空间。
c.shrink_to_fit() 此操作要求容器退回不需要的内存空间,将capacity()减小为与size()相同大小。
**shrink_to_fit()只适用于vector、string和deque。
capacity()和reserve()只适用于vector和string。**
capacity和size的区别在于size是指容器已经保存了多少个元素,而capacity表示容器最多可以保存多少元素。

9.string操作:
① 构造string:
这里写图片描述
这里写图片描述
这里写图片描述

② 改变string的操作:
这里写图片描述
这里写图片描述

③ string搜索操作:
这里写图片描述
这里写图片描述

④ compare函数:
类似strcmp,根据s是等于、大于还是小于参数制定的字符串,s.compare返回0、正数或负数。
这里写图片描述

⑤ 数值转换:
这里写图片描述

10.容器适配器:
标准库定义了三个顺序容器适配器:stack、queue和priority_queue。
默认情况下,stack和queue是基于deque实现的,priority_queue是在vector之上实现的。

定义一个适配器:
//默认构造函数创建一个空对象,接收一个容器的构造函数拷贝该容器来初始化适配器。
deque<int> deq;
stack<int> stk(deq); //从deq拷贝元素到stk

//可以在创建一个适配器时将一个命名的顺序容器作为第二个类型参数来重载默认容器类型。
stack<string, vector<string>> str_stk;  //在vector上实现空栈
stack<string, vector<string>> str_stk2(svec); //str_stk2在vector上实现,初始化时保存svec的拷贝

所有适配器都要求容器具有添加、删除以及访问尾元素的能力。因此:
stack只要求push_back、pop_back和back操作,可以使用除array和forward_list之外的任何容器类型来构造。

//栈适配器的一些操作
#include<stack>
stack<int> intStack;    //空栈
//填满栈
for(size_t ix=0;ix!=10;ix++)
        intStack.push(ix);       //intStack保存0到9十个数
while(!intStack.empty())
{
     int value=intStack.top();
     //使用栈顶值的代码      
     intStack.pop();            //弹出栈顶元素,继续循环
}

这里写图片描述
queue适配器要求back、push_back、front和push_front,因此他可以构造于list或deque之上,但不能基于vector构造。
priority_queue除了front、push_back和pop_back操作之外还要求随机访问能力,因此他可以构造于vector或deque之上,但不能基于list构造。
这里写图片描述
这里写图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值