一、顺序容器概述

  一个容器就是一些特定类型对象的集合。顺序容器为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。

  顺序容器类型:

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

  string和vector将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是,在这两种容器的中间位置添加或删除元素就会非常耗时。

  list和forward_list这两个容器的设计目的是令容器任何位置的添加和删除元素都很快速。作为代价,这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器。而且,与vector、deque和array相比,这两个容器的额外内存开销也很大。

  deque是一个更为复杂的数据结构。与string和vector类似,在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都是很快的(只花费常数时间),与list和forward_list添加删除元素的速度相当。

  forward_list和array是新C++标准增加的类型。与内置数组相比,array是一种更安全、更容易使用的数组类型。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。

二、容器库概述

  一般来说,每个容器都定义在一个头文件中,文件名与类型名相同。

  顺序容器几乎可以保存任意类型的元素。特别是,我们可以定义一个容器,其元素的类型是另一个容器。这种容器的定义与任何其他容器类型完全一样。但某些容器操作对元素类型有其自己的特殊要求。我们可以为不支持特定操作需求的类型定义容器,但这种情况下就只能使用那些没有特殊要求的容器操作了。

  所有容器类型(也包括关联容器)都支持的操作:

类型别名 说明
iterator 此容器类型的迭代器类型
const_iterator 可以读取元素,但不能修改元素的迭代器类型
size_type 无符号整数类型,足够保存此种容器类型最大可能容器的大小
difference_type 带符号整数类型,足够保存两个迭代器之间的距离
value_type 元素类型
reference 元素的左值类型;与value_type&含义相同
const_reference 元素的const左值类型(即,const value_type&)
构造函数  
C c; 默认构造函数,构造空容器(array不支持)
C c1(c2); 构造c2的拷贝c1
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.swap(b)等价
大小  
c.size() c中元素的数目(不支持forward_list)
c.max_size() c可保存的最大元素数目
c.empty() 若c中存储了元素,返回false,否则返回true

添加/删除元素(array不支持)

注:在不同容器中,这些操作的接口都不同

 
c.insert(args) 将args中的元素拷贝进c
c.emplace(inits) 使用inits构造c中的一个元素
c.erase(args) 删除args指定的元素
c.clear() 删除c中的所有元素,返回void
关系运算符  
==, != 所有容器都支持相等(不相等)运算符
<, <=, >, >= 关系运算符(无序关联容器不支持)
获取迭代器  
c.begin(), c.end() 返回指向c的首元素和尾元素之后位置的迭代器
c.cbegin(), c.cend() 返回const_iterator
反向容器的额外成员(不支持forward_list)  
reverse_iterator 按逆序寻址元素的迭代器
const_reverse_iterator 不能修改元素的逆序迭代器
c.rbegin(), c.rend() 返回指向c的尾元素和首元素之前位置的迭代器
c.crbegin(), c.crend() 返回const_reverse_iterator
   

1、迭代器

  标准容器迭代器的运算符:

运算符 说明
*iter 返回迭代器iter所指元素的引用
iter->mem 解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++iter 令iter指向容器的下一个元素
--iter 令iter指向容器中的上一个元素
iter1 == iter2 判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等
iter1 != iter2  

其中,forward_list迭代器不支持递减运算符(--)。

  string、vector、deque、array的迭代器支持的算术运算:

算术运算 说明
iter + n 迭代器加上一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向前移动了若干个元素。结果迭代器或者指示容器内的一个元素,或者等于容器尾后迭代器
iter - n 迭代器减去一个整数值仍得一个迭代器,迭代器指示的新位置与原来相比向后移动了若干个元素
iter += n 迭代器加法的复合赋值语句,将iter加n的结果赋给iter
iter -= n 迭代器减法的复合赋值语句,将iter减n的结果赋给iter
iter1 - iter2 两个迭代器相减的结果是它们之间的距离。参与运算的必须是同一个容器的迭代器
>、>=、<、<= 迭代器的关系运算符,如果某迭代器指向的容器位置在另一个迭代器所指位置之前,则说明前者小于后者。参与运算的必须是同一个容器的迭代器

注意:上面的迭代器的范围区间是[begin(),end()],如果运算结果不在这个区间内,会报错。

  

  一个迭代器范围是由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者尾元素之后的位置。这两个迭代器通常被称为begin和end。这种元素范围被称为左闭右合区间,其标准数学描述为:[begin, end)。

  当auto与begin或end结合使用时,获得的迭代器类型依赖于容器类型,如果对象是常量,返回const_iterator;如果对象不是常量,返回iterator。cbegin和cend不论对象是否是常量,返回值都是const_iterator。

2、容器定义和初始化

操作 说明
C c 默认构造函数。如果c是一个array,则c中元素按默认方式初始化;否则c为空
C c1(c2) c1初始化为c2的拷贝。c1和c2必须是相同类型(即,它们必须是相同的容器类型,且保存的是相同的元素类型;对于array来说,两者还必须具有相同大小)
C c1=c2 同上
C c{a, b, c, ...} c初始化为初始化列表中元素的拷贝。列表中元素的类型必须与c的元素类型相容。对于array类型,列表中元素数目必须等于或小于array的大小,任何遗漏的元素都进行值初始化。初始化列表隐含地指定了容器的大小:容器将包含与初始值一样多的元素。
C c={a, b, c, ...} 同上
C c(b, e) c初始化为迭代器b和e指定范围中的元素的拷贝。范围中元素的类型必须与c的元素类型相容(array不适用)
只有顺序容器(不包括array)的构造函数才能接受大小参数  
C seq(n) seq包含n个元素,这些元素进行了值初始化;此构造函数是explicit的
C seq(n, t) seq包含n个初始化为值t的元素

  将一个容器初始化为另一个容器的拷贝的例子:

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <deque>
 5 #include <list>
 6 #include <forward_list>
 7 #include <array>
 8
 9 int main()
10 {
11     std::list<std::string> authors = { "abc", "QAQ", "hello" };
12     std::vector<const char*> articles = { "a", "ab", "the" };
13
14     std::list<std::string> list2(authors); // 类型匹配
15     //std::deque<std::string> auth(authors); // 错误:容器类型不匹配
16     std::forward_list<std::string> words(articles.begin(), articles.end()); // 元素类型可以相互转换
17     return 0;
18 }

View Code

1)标准库array具有固定大小

  与内置数组一样,标准库array的大小也是类型的一部分。当定义一个array时,除了指定元素类型,还要指定容器大小。使用array时也要指定容器大小。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <deque>
 5 #include <list>
 6 #include <forward_list>
 7 #include <array>
 8
 9 int main()
10 {
11     std::array<int, 10> arr; // 类型为10个int的数组
12     std::array<int, 10>::size_type i; // 数组类型包括元素类型和大小
13     return 0;
14 }

View Code

  一个默认构造的array是非空的:它包含了与其大小一样多的元素。这些元素都被默认初始化。如果我们对array进行列表初始化,初始值的数目必须等于或小于array的大小。如果初始值数目小于array的大小,则它们被用来初始化array中靠前的元素,所有剩下的元素都会进行值初始化。

  虽然我们不能对内置数组类型进行拷贝或对象赋值操作,但array并无此限制。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <deque>
 5 #include <list>
 6 #include <forward_list>
 7 #include <array>
 8
 9 int main()
10 {
11     std::array<int, 10> arr = { 2, 3 };
12     std::array<int, 10> copy = arr;
13     return 0;
14 }

View Code

3、赋值和swap

  赋值运算符将其左边容器中的全部元素替换为右边容器中元素的拷贝。

  所有容器都支持的赋值运算:

操作 说明
c1=c2 将c1中的元素替换为c2中元素的拷贝。c1和c2必须具有相同的容器类型,且保存的是相同的元素类型
c={a, b, c, ...} 将c1中的元素替换为初始化列表中元素的拷贝(array不适用)。保存的必须是相同的元素类型
swap(c1, c2) 交换c1和c2中的元素。c1和c2必须具有相同的类型。swap通常比从c2向c1拷贝元素快得多
c1.swap(c2) 同上
assign操作不适用于关联容器和array  
seq.assign(b, e) 将seq中的元素替换为迭代器b和e所表示的范围中的元素。迭代器b和e不能指向seq中的元素。保存的元素类型必须相容。
seq.assign(items) 将seq中的元素替换为初始化列表items中的元素
seq.assign(n, t) 将seq中的元素替换为n个值为t的元素 

  赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效。

  swap操作将容器内容交换不会导致指向容器的迭代器、引用和指针失效(容器类型为array和string的情况除外)。

1)使用assign(仅顺序容器)

  顺序容器(array除外)还定义了一个名为assign的成员,允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。

 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 #include <deque>
 5 #include <list>
 6 #include <forward_list>
 7 #include <array>
 8
 9 int main()
10 {
11     std::vector<int> vec = { 1, 2, 3 };
12     std::vector<double> vec2 = { 4.5, 5.5, 6.5 };
13     // vec = vec2; // 错误:类型不同
14     std::list<double> lst = { 7, 8, 9 };
15     vec.assign(lst.begin(), lst.end());
16     return 0;
17 }

View Code

2)使用swap

  除array外,交换两个容器内容的操作保证会很快----元素本身并未交换,swap只是交换了两个容器的内部数据结构。

  元素不会被移动的事实意味着,除string外,指向容器的迭代器、引用和指针在swap操作都不会失效。他们仍然指向操作之前所指向的那些元素。但是,在swap之后,这些元素已经属于不同的容器了。

  对一个string调用swap会导致迭代器、引用和指针失效。

  swap两个array会真正交换它们的元素。因此,交换两个array所需的时间与array中元素的数目成正比。

  因此,对于array,在swap操作之后,指针、引用和迭代器所绑定的元素保持不变,但元素值已经与另一个array中对应元素的值进行了交换。

5、关系运算符

  每个容器类型都支持相等运算符(==和!=);除了无序关联容器外的所有容器都支持关系运算符(>、>=、<、<=)。关系运算符左右两边的运算对象必须是相同类型的容器,且必须保存相同类型的元素。

  比较两个容器实际上是进行元素的比较。这些运算符的工作方式与string的关系运算类似:

a、如果两个容器具有相同大小且所有元素都两两对应相等,则这两个容器相等;否则两个容器不等。

b、如果两个容器大小不同,但较小容器中每个元素都等于较大容器中的对应元素,则较小容器小于较大容器。

c、如果两个容器都不是另一个容器的前缀子序列,则它们的比较结果取决于第一个不相等的元素的比较结果。

  只有当其元素类型也定义了相应的比较运算符时,我们才可以使用关系运算符比较两个容器。

  容器的相等运算实际上是使用元素的==运算符实现比较的,而其他关系运算符是使用元素的<运算符。如果元素不支持所需运算符,那么保存这种元素的容器就不能使用相应的关系运算。

转载于:https://www.cnblogs.com/ACGame/p/10219585.html

顺序容器----顺序容器概述,容器库概览相关推荐

  1. C++primer第九章 顺序容器 9.1 顺序容器概述 9.2容器库概览

    一个容器就是一些特定类型对象的集合.顺序容器(sequentialcontainer)为程序员提供了控制元素存储和访问顺序的能力.这种顺序不依赖于元素的值,而是与元素加入容器 时的位置相对应.与之相对 ...

  2. 第十一篇:(顺序)容器的好伴侣 --- 容器适配器

    前言 vector容器的数据结构原型是顺序表,它很好的实现了顺序表的功能,大大方便了编程.好了,现在假设有天我又想用栈,那么有没有栈对应的容器呢?很遗憾,木有.但基于"栈"可以由顺 ...

  3. STL 容器简介:C++ 容器:顺序性容器、关联式容器和容器适配器

    STL标准容器类简介 标准容器类 说明 顺序性容器 vector 从后面快速的插入与删除,直接访问任何元素 deque 从前面或后面快速的插入与删除,直接访问任何元素 list 双链表,从任何地方快速 ...

  4. 2021年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题

    题库来源:特种作业模考题库小程序 2021年R1快开门式压力容器操作证模拟考试题库及R1快开门式压力容器操作理论考试试题是由特种作业模考题库提供,R1快开门式压力容器操作证模拟考试题库是根据R1快开门 ...

  5. 2021年R2移动式压力容器充装证考试题库及压力容器作业R2移动式压力容器充装试题解析

    题库来源:特种作业模考题库小程序 1.<特种设备安全法>规定,县级以上地方各级人民政府负责对本行政区域内特种设备安全实施监督管理. × 2.压力容器均应由产权单位向登记机关办理使用登记证. ...

  6. 2021年R2移动式压力容器充装证考试题库及R2移动式压力容器充装试题解析

    题库来源:特种作业模考题库小程序 2021年R2移动式压力容器充装证考试题库及R2移动式压力容器充装试题解析是结合(安监局)特种作业人员操作证考试大纲和(质检局)特种设备作业人员上岗证考试大纲随机出的 ...

  7. 2022年R1快开门式压力容器操作操作证考试题库及在线模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022R1快开门式压力容器操作培训试题系R1快开门式压力容器操作模拟考试试题全真模拟题!2022年R1快开门式压力容器操作操作证考试题库及在线模拟考试根 ...

  8. EJB是什么Java使用EJB容器的详细概述

    EJB是什么 博客分类: java EJB  最近项目中接触到EJB,但对EJB不是很了解,于是网上找了些资料参考,下面这篇是个人感觉讲的比较清晰的,遂转载一起参考,文章转自https://www.c ...

  9. 2021年压力容器作业R2移动式压力容器充装证考试题库

    题库来源:特种作业模考题库小程序 1..爆破片应进行定期更换,一般情况下爆破片应( )更换. B A.1-2年 B.2-3年 C.3-4年 2.充装毒性程度为高度危害.自燃及强氧化性介质的长管拖车或者 ...

最新文章

  1. 北航与西安交大计算机专业对比,北航和西安交大,谁的工科实力更强,该上哪一所大学呢?...
  2. 循环中 动态参数 传div 层_【转载】黄学杰等:铌元素在锂离子电池中的应用
  3. Vuex-状态管理模式
  4. PMP读书笔记(第1章)
  5. Linux内核学习-字符设备驱动学习(二)
  6. python 函数参数多个逗号不报错_python笔记7-多线程threading之函数式
  7. 动态加载网上或者本地场景的后续
  8. jq中使用promise封装ajax
  9. TypeScript + Gulp + 混淆 + 打包
  10. Lena图像原图及由来
  11. itchat使用教程
  12. android 模拟器创建,Android模拟器的建立以及HelloWorld的编写
  13. f(x)和g(x)分别是概率密度函数,h(x)=f(x)g(x)还会是概率密度函数么?
  14. mysql获取今天的最后一秒_Oracle取得当天0时0分0秒和23时59分59秒
  15. 【手写dubbo-2】超详细!netty实现群聊、私聊
  16. go语言零知识证明gnark框架
  17. 几种常见的Kafka集群监控工具「送书」
  18. Flutter 全能型选手GetX —— 状态管理
  19. 为何要重建索引 index
  20. MySQL数据库——备份与恢复

热门文章

  1. c语言更新数据,sqlite学习笔记10:C语言中使用sqlite之查询和更新数据
  2. hp服务器raid制作,HP服务器建立RAID的两种方法
  3. h5页面笔按下默认是拖动_屡屡刷屏的长页面H5原来是这样诞生的
  4. 【linux】截断日志文件
  5. php判断ie版本,PHP获取浏览器版本信息
  6. codematic2连接mysql失败_codematic2.rar
  7. bootstraptable 汇总_bootstrap-table事件汇总
  8. go语言实现将word文件转成pdf_超实用的PDF在线转换器,你绝对用的到~
  9. 云服务器磁盘挂载_云小课 | 磁盘容量不够用?小课教你来扩容!
  10. ab压力 failed_Apache ab 压力测试