C++顺序容器笔记

题记:
关于容器,  C++primer  有详细描述,网上也有各种资料,而我写这篇文章的意义在于:阅读  C++primer  之后的总结、复习以及理解。
概念
容器(  container ),保存一组给定类型对象的类型。  因为引用不是对象,所以,容器的类型不能是引用。  每个标准库容器类型都是一个模板类型。为了定义容器,我们必须指定保存在容器中元素的类型。除了  array  之外,标准库容器的大小都是可变的。
顺序容器  (sequentail container)  ,元素在容器的顺序,和加入容器时的位置相对象,元素通过位置来访问。
关联容器(  associative container  ),元素通过关键字高效访问。
vector  ,顺序容器,可变大小数组,  vector  中的元素可以通过下标访问,支持快速随机访问。在尾部插入或者删除元素效率很高,其他位置插入删除元素会导致数组重新分配空间,效率有限。在  vector  添加或者删除元素,如果导致内存重新分配,那么整个迭代器都会失效,否则,修改点之后的迭代器失效。
deque  ,顺序容器,双端队列。元素可通过下标访问,支持快速随机访问,支持在头尾快速插入删除元素。  deque  在各方面都和  vector 类似,唯一的差别是,支持在容器的头尾快速删除插入元素,而且两端的插入删除操作不会导致重新分配空间。
list  ,双向链表,只支持双向顺序访问。从一个给定元素开始,为了访问另一个元素,需要遍历链表。可在任何位置高效的插入删除元素而不使迭代器失效(除了删除的元素之外)。
forward_list  ,单向链表。  C++11 新加入,元素只能顺序访问。其设计目标是达到于最好的手写单链表有相当的性能。因此,  forward_list  没有 size  操作。
array  ,固定大小数组,创建时必须给定大小。支持快速随机访问,不能添加或者删除元素。
string  ,与 vector  相似的容器,但专门用于保存字符。
在顺序容器中,除了固定大小的  array  之外,其他容器都提供高效的、灵活的内存管理。可以添加、删除、扩张或者缩小容器大小。容器保存元素的策略(内部数据结构),对容器的操作效率有固定的重大的影响。某些情况下,策略还决定是否支持容器特定操作。
例如,  vector   string  都是将元素保存在连续的内存空间,可以用下标快速访问,但是要在中间插入或者删除元素,就会破坏空间的连续性,导致移动修改点之后的元素或者重新分配空间来保持空间连续性,所以,插入删除效率就不高。相对的,  list  是以链表的形式保存元素的,所以,插入或者删除元素都很快,只需重新维护插入删除位置的链表即可,但是不支持随机访问,需遍历链表。而且,相对于  vector   list  的内存开销会很大。而  deque  是一个更为复杂的数据结构,详情可参考  http://www.cnblogs.com/zhangchaoyang/articles/2277209.html  。总之,容器的内部数据结构决定其访问能力、效率。
迭代器
迭代器是一种类型,用于访问容器中的元素或者再元素之间移动。迭代器的实现可能是指针、也可能是类,参考  http://blog.youkuaiyun.com/yxysdcl/article/details/5567460
标准容器迭代器的运算符:  iter->mem  (解引用)、  *iter (返回元素引用)、  ++   --   == 、!  =  ,其中 forward_list  不支持   运算。除此之外,  vector   string   deque   array  的迭代器还支持以下运算:  +n   -n   +=n   -=n   iter1-iter2   >   <   <=   >=
迭代器范围:一个迭代器范围由一对迭代器表示,分别指向同一容器不同元素,为左闭合区间。
反向迭代器:按逆序寻址元素的迭代器,不支持  forward_list  
begin()  返回容器第一个元素的迭代器;  rbegin()  返回反向迭代的第一个元素;  cbegin()  返回 const  类型的迭代器。其中不以  c  开头的 begin   rbegin 是重载过的,有两个版本,分别返回  iterator   const_iterator  类型。对应的  end()   rend()   cend()   crend()  类似。以 c  开头的迭代器是  C++11  新引入的,结合  auto 使用比较方便。另外,  forward_list  还有一个首前迭代器,返回第一个元素之前的迭代去,  before_begin(),cbefore_begin()  
定义和初始化

其中,表格中第二个构造函数  C c1(c2)   c1   c2 必须有相同的类型,否则报错。其他函数满足类型的隐式转换也可以。使用大括号的第四个和第五个为列表初始化,显示的指定每个元素的值,同时,隐式的指定了容器的大小(  array  )除外。特别的  vector<string> v{10   “hi”} 定义  10  个值为 hi  的元素的容器,  vector<string> v{10}  定义 10  个值为空的元素的容器。
赋值和  swap

赋值运算符要求左边和右边的运算对象具有完全相同的类型。  assign  允许我们从一个不同但相容的类型赋值,或者从容器的子序列赋值。例如,可以使用  assign  讲一个 vector  中的一段  char*  值赋予一个 list  中的  string
添加元素

array  是固定数组。  forward_list 是单链表,故此,不支持  push_back   emplace_back  。同理  vector   string  是动态数组,不支持在头部插入数据。
insert   emplace  在容器的特定位置插入元素,该位置由第一个参数  p  (迭代器)指定,在  p 之前插入后续参数指定的元素,返回插入的第一个元素的迭代器。
C++11  标准引入了三个  emplace 成员,这些操作直接构造元素,例如:


访问元素
迭代器解引用、  back   front   at   []  。访问成员函数返回的是引用,可以直接用来改变元素的值。但是,在使用  auto  定义变量时,会忽略引用和顶层  const  类型,需自己添加。
删除元素

特殊的 forward_list操作

ps:

1、 容器类型不能是引用,因为引用并不是类型。

2、 接受容器大小的构造函数seq(n),其类型是explicit的,不能对类型隐式转换。如

vector<string> s("ee"); //error无构造函数可以接受源类型

当使用该构造函数时,需使用元素的默认构造函数取创建元素,所以,必须保证元素有默认构造函数。如:

// 假定Nodefault是一个没有默认构造函数的类型

         vector<Nodefault>v1(10, init);  //ok 提供了元素的初值

vector<Nodefault>v1(10);        // error 没有初值,无法初始化

3、 array不支持普通的容器构造函数,元素被默认初始化。如

array<int, 10> i;   // 默认初始化为0

array<string, 2> ss = {"123" };   //第一个元素为123,后一个元素为空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值