元素在顺序容器中的顺序与其加入容器时的位置相对应。关联容器中元素的位置由元素相关联的关键字值决定。所有容器类都共享公共的接口,不同容器按不同方式对其进行扩展。

  一个容器就是一些特定类型对象的集合。顺序容器为程序员提供了控制元素存储和访问顺序的能力。

1. 顺序容器概述

容器的两种性能:

  • 向容器中添加或删除元素的代价
  • 非顺序访问容器中元素的代价

顺序容器类型:

如何确定使用哪种顺序容器

NOTE:通常情况下,使用vector是最好的选择。根据使用的需求对容器的哪种性能更加看重来选择合适的容器。

2. 容器库概览

容器类型上的操作有三个层次:

  • 某些操作是所有容器类型都提供的
  • 另外一些操作仅针对顺序容器、关联容器或无序容器
  • 还有一些操作只适用于一小部分容器

每个容器都定义在一个头文件中,文件名与类型名相同。容器均定义为模板类。

以下容器操作是所有容器类型所共有的操作

2.1 迭代器

迭代器范围

一个迭代器范围由一对迭代器表示,begin指向容器的首元素,end指向容器的尾元素之后的位置。

迭代器范围是一个左闭合区间,[begin, end)。

begin可以和end指向同一个位置,但是end不能指向begin之前的位置。

2.2 容器类型成员

处理迭代器之外还有反向迭代器,对反向迭代器进行++操作,会得到上一个元素。

通过value_type得到元素类型,通过reference或const_reference得到元素类型的一个引用。

2.3 标准库array具有固定大小

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

array<int, 42>  arr;

其构造函数和数组差不多,列表初始化时,列表元素不要超过array的大小,可以少,array剩下的元素就进行值初始化。

array<int, 10> a={1,2,3};

剩下的7个元素值初始化为0;

此外还可以对array进行拷贝或对象赋值操作,但内置数组是不支持的

int a1[3]={0,1,2};
int a2[3]=a1; //错误
array<int, 3> a3={0,1,2};
array<int, 3> a4=a3; //正确

拷贝或赋值要保证类型相同。

2.4 赋值和swap

注意array在初始化的时候可以进行列表初始化,但是赋值的时候不能将一个花括号列表赋值给它。

NOTE:array赋值的时候,两边的运算对象必须具有相同的类型。

array<int, 3> a1 = { 0, 1, 2 };
array<int, 3> a2 = { 0 };
array<int, 3> a3 = { 2, 3, 4 };
a1 = a2;
a3 = { 0 }; //错误

对a3赋值的时候,a3的类型是array<int,3>,而右边是先把{0}转换成临时变量array<int,1> tmp,然后再将tmp赋值给a3,这是tmp和a3类型不一致。

由于可能因为大小不一致导致类型不一致,array不支持容器的赋值运算assign。

NOTE:assign操作仅适合顺序容器

赋值运算符要求左右两边的运算对象具有相同的类型,将右边运算对象所有元素拷贝到左边运算对象中。

swap

swap交换两个相同类型容器的内容。swap操作并不会交换元素本身,知识交换两个容器的内部数据结构(除array外)。这就意味着,指向容器的迭代器、引用和指针在swap操作之后都不会失效,仍指向swap操作之前的那些元素,只是这些元素属于不同容器了。

swap两个array会真正交换他们的元素。

有两个版本的swap:成员函数版本以及非成员版本,统一使用非成员版本的swap。

2.5 容器大小操作

  • size:forward_list不支持size
  • empty
  • max_size

2.6 关系运算符

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

关系比较规则:

对元素进行逐对比较。大小相同、对应元素相等则相等;元素相等,大小不等,小的小于大的;都不相等,则比较第一个不相等的元素。

NOTE:只有当容器的元素定义了相应的比较运算符操作时,才可以使用关系运算符。

3. 顺序容器操作

顺序容器和关联容器的不同之处在于两者组织元素的方式。这些不同之处直接关系到了元素如何存储、访问、添加以及删除。接下来的操作都是顺序容器所独有的操作。

3.1 向顺序容器中添加元素

新标准引入了三个新成员:emplace_front 、emplace和emplace_back,这些操作构造而不是拷贝元素。

当调用push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用emplace成员函数时,则是将参数传递给元素类型的构造函数。

empalce函数的参数根据元素类型而变化,参数必须与元素类型的构造函数相匹配。

c.empalce("978-001",25,15.99);    //用三个参数直接构造对象
c.push_back("978-001",25,15.99); //错误,没有接受三个参数的push_back版本
c.push_back(Sales_data("978-001",25,15.99)); //正确

NOTE:emplace函数在容器中直接构造元素,而push_back则是创建临时对象。

3.2 访问元素

访问成员函数返回的是引用

front、back、下标和at,其返回的都是引用。

如果我们使用auto变量来保存这些函数的返回值,并且希望使用此变量来改变元素的值,必须记得将变量定义为引用类型。

auto &v=c.back();    //获得指向最后一个元素的引用
auto v=c.back(); //v不是一个引用,是c.back()的一个拷贝

下标操作必须保证在范围内操作

3.3 删除元素

3.4 特殊的forward_list操作

forward_list并未定义insert、emplace和erase,而是定义了名为insert_after、emplace_after和erase_after的操作。

3.5 改变容器大小

list<int> ls(10,45);    //10个int,都是45
ls.resize(15); //将5个值为0的元素添加到ls的末尾
ls.resize(25,-1); //将10个值为-1的元素添加到ls的末尾
ls.resize(5); //从ls末尾删除20个元素

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

由于向迭代器添加元素和从迭代器删除元素的代码可能会使迭代器失效,因此必须保证每次改变容器的操作之后都正确地重新定位迭代器。

4. vector对象是如何增长的

每次都比实际所需空间多分配点空间,而不是每次都把所有元素移动到新空间。

管理容量的成员函数

capacity和size

size是指已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。

NOTE:只有当迫不得已时才可以分配新的内存空间。

5. 额外的string操作

5.1 构造string的其他方法

string定义的这些额外操作要么是提供string类和C风格字符数组之间的相互转换,要么是增加了允许我们用下标代替迭代器的版本。

substr操作

substr返回一个string,它是原始string的一部分或全部的拷贝,可以传递给substr一个可选的开始位置和计数值。

5.2 改变string的其他方法

string类型支持顺序容器的赋值运算符以及assign、insert和erase操作。除此之外,还定义了额外的insert和erase版本。

s.insert(s.size(),5,'!');    //在s末尾插入5个感叹号
s.erase(s.size()-5,5); //从s删除最后5个字符 const char *cp="Stately, plump Buck";
s.assign(cp,7); //s=="Stately"
s.insrt(s.size(),cp+7); //s=="Stately, plump Buck" string s="some string", s2="some other string";
s.insert(0,s2); //在s中位置0之前插入s2的拷贝
s.insert(0,s2,0,s2.size());

5.3 string搜索操作

搜索是大小写敏感的

逆向搜索

rfind成员函数搜索最后一个匹配,即子字符串最靠右的出现位置。

5.4 compare函数

5.5 数值转换

6. 容器适配器

除了顺序容器外,标准库还定义了三个顺序容器适配器:stack、queue和priority_queue。容器、迭代器和函数都有适配器。

本质上,一个适配器是一种机制,能使某种事物的行为看起来像另一种事物一样。

一个容器适配器接受一种已有的容器类型,使其行为看起来像一种不同的类型。

C++系统学习之九:顺序容器的更多相关文章

  1. C++学习基础四——顺序容器和关联容器

    —顺序容器:vector,list,queue1.顺序容器的常见用法: #include <vector> #include <list> #include <queue ...

  2. 【mongodb系统学习之九】mongodb保存数据

    九.mongodb保存数据: 1).插入.保存数据:insert:语法db.collectionName.insert({"key":value}),key是字段名,必须是字符串( ...

  3. Linux系统学习 十九、VSFTP服务—虚拟用户访问—为每个虚拟用户建立自己的配置文件,单独定义权限

    为每个虚拟用户建立自己的配置文件,单独定义权限 可以给每个虚拟用户单独建立目录,并建立自己的配置文件.这样方便单独配置权限,并可以单独指定上传目录 1.修改配置文件 vi /etc/vsftpd/vs ...

  4. 系统学习 Java IO (九)----缓冲流 BufferedInputStream/BufferedOutputStream

    目录:系统学习 Java IO---- 目录,概览 BufferedInputStream BufferedInputStream 类为输入流提供缓冲. 缓冲可以加快IO的速度. BufferedIn ...

  5. Docker学习(九)Volumn容器间共享数据

    Docker学习(九)Volumn容器间共享数据 volume是什么 volume在英文中是容量的意思, 在docker中是数据卷的意思,是用来保存数据的容器 为什么要进行数据共享 在集群中有多台to ...

  6. Docker 容器数据 持久化(系统学习Docker05)

    写在前面 本来是可以将数据存储在 容器内部 的.但是存在容器内部,一旦容器被删除掉或者容器毁坏(我亲身经历的痛,当时我们的大数据平台就是运行在docker容器内,有次停电后,不管怎样容器都起不来.以前 ...

  7. c++ 顺序容器学习

    所谓容器,就是一个装东西的盒子,在c++中,我们把装的东西叫做“元素” 而顺序容器,就是说这些东西是有顺序的,你装进去是什么顺序,它们在里面就是什么顺序. c++中的顺序容器一共有这么几种: vect ...

  8. 【c++ Prime 学习笔记】第9章 顺序容器

    一个容器是特定类型对象的集合 顺序容器中元素的顺序与其加入容器的位置对应 关联容器中元素的顺序由其关联的关键字决定,关联容器分为有序关联容器和无序关联容器 所有容器类共享公有接口,不同容器按不同方式扩 ...

  9. Unity3D 装备系统学习Inventory Pro 2.1.2 基础篇

    前言 前一篇 Unity3D 装备系统学习Inventory Pro 2.1.2 总结 基本泛泛的对于Inventory Pro 这个插件进行了讲解,主要是想提炼下通用装备系统结构和类体系.前两天又读 ...

随机推荐

  1. How to install your SSL Certificate to your Windows Server

    Installation: Open the ZIP file containing your certificate. Save the file named your_domain_name.ce ...

  2. LDAP理论知识

    整理改编自: https://www.cnblogs.com/yjd_hycf_space/p/7994597.html http://blog.51cto.com/407711169/1439623 ...

  3. 双系统更新ubuntu后,启动引导项消失,无法进入windows

    1.打开终端输入命令sudo gedit /etc/default/grub 2.修改GRUB_TIMEOUT="10" 3.输入sudo update-grub( update ...

  4. Python模块之re

    re模块 准备: flags有很多可选值: re.I(IGNORECASE)忽略大小写,括号内是完整的写法 re.M(MULTILINE)多行模式,改变^和$的行为 re.S(DOTALL)点可以匹配 ...

  5. 浮点数据与IEE754

    在计算机系统(包括单片机)中,浮点数(单精度float和双精度的double)对采用IEE-754标准.该标准为 32 位浮点和 64 位双精度浮点二进制小数定义了二进制标准. IEEE 754 用科 ...

  6. cordova开发的坑

    相机 根据android版本,有各种问题. 1.拍照后不会自动清内存造成内存溢出,导致照片不会自动旋转,拍多张之后会自动刷新网页. 2.小米手机安卓7.0时,拍出的照片不会自动旋转,需要安卓端代码调整 ...

  7. left join \ right join \ inner join 详解

    left join 和 left outer join 的区别 通俗的讲:   A   left   join   B   的连接的记录数与A表的记录数同   A   right   join   B ...

  8. 《C#高效编程》读书笔记01-使用属性而不是可访问的数据成员

    在需求变更中,属性比数据成员更容易修改,例:客户对象不该与空白名称,若你使用公有属性封装Name,那么现在修改一处,而数据成员则可能要修改多处 public class Customer { priv ...

  9. MoinMoin install in apache (win)

    一:下载环境 xampp:http://sourceforge.net/projects/xampp/files/XAMPP%20Windows/1.8.1/xampp-win32-1.8.1-VC9 ...

  10. If you can't take it, don't dish it out.

    If you can't take it, don't dish it out.己所不欲,勿施于人.