细嚼慢咽C++primer(5)——顺序容器

1 顺序容器的定义

容器是容纳特定类型对象的集合。

顺序容器:将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素,这就是顺序容器。

标准库的三种顺序容器类型:vector, list 和 deque。

适配器:stack,queue和priority_queue类型。适配器是根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。


头文件:

#include<vector>
#include<list>
#include<deque>


所有的容器都是类模板,要定义某种特殊的容器,必须在容器名后加一对尖括号,尖括号里面提供容器中存放的元素的类型:

vector<string> svec;
list<int> ilist;
deque<Sale_item> items;

容器类型最好使用默认构造函数。

2 四种创建和初始化vector对象的方式

vector<int> ivec1(6);
vector<int> ivec2(6,1);
vector<int> ivec3(ia, ia+6);
vector<int> ivec4(ivec1);


Q:复制容器对象的构造函数和使用两个迭代器的构造函数之间的差别。
A: 复制容器对象的构造函数只能在相同类型的容器间进行完全的复制,而使用迭代器的构造函数可以将一个容器的子序列赋值给另一个容器,并且容器的类型也不要求必须相同,只要容器中的元素可以兼容即可。


3 容器内元素的类型约束

  • 元素类型必须支持赋值运算
  • 元素类型的对象必须可以复制

除了引用类型外,所有内置或符合类型都可用做元素类型,引用不支持一般意义的赋值运算,因此所有元素是引用类型的容器。

IO库类型不支持复制和赋值, 所以,不能创建存放IO类型对象的容器,


容器的容器:

vector< vector<string> > lines;
必须用空格隔开两个相邻的 > 符号,以示这是两个分开的符号。


4 迭代器和迭代器范围

Q: 下面的程序错在哪里?如何更正?

list<int> lst1;
list<int>::iterator iter1 = lst1.begin(),
                            iter2 = lst1.end();
while (iter1 < iter2)
        ........

A: list容器的迭代器不支持关系操作符,关系操作符只属用于vector和deque容器。


4.1 迭代器范围

迭代器范围,标记同一个容器中的两个元素或超出末端的下一位置,通常命名它们为first和last, 或begin和end。

其中,第二个迭代器从来都不是指向元素范围的最后一个元素,而是指向最后一个元素的下一位置。


对形成迭代器范围的两个迭代器的要求:

  • 它们指向同一个容器中的元素或超出末端的下一个位置;
  • 如果这两个迭代器不相等,则对first反复做自增运算必须能够到达last, 换句话说,在容器中,last绝对不能位于first之前。

4.2 迭代器失效

使用迭代器编写程序时,必须留意哪些操作会使迭代器失效,使用无效的迭代器将会导致严重的运行时错误。

任何insert或push操作都可能导致迭代器失效,当编写循环将元素插入到vector或deque容器中时,程序必须确保迭代器在每次循环后都得到更新。


4.3 容器间的比较

比较规则:

如果两个容器具有相同的长度,而且所有元素都相等,那么这两个容器就相等,否则,它们就不相等;

如果两个容器的长度不相同,但较短的容器中所有元素都等于较长容器中对应的元素,则称较短的容器小宇另一个容器;

如果两个容器都不是对方的初始子序列,则它们的比较结果取决于所比较的第一个不相等的元素。


4.4 vector容器的内存分配,size和capacity的区别

虽然一直都是在说一些基础的东西,但是容器的操作网上很多,很容易查得到,就不再赘述。说一说vector容器是如何实现内存的快速分配的吧。

为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需要的空间要多一些。预留的这个空间是为了存放新添加的元素。

vector<int> ivec;
ivec.size();  // 所保存的元素数目
ivec.capacity(); //实际可以容纳的元素数目

所以一般来说,capacity比size要大一些。


总结一句话就是,通常来说,除非找到选择使用其他容器的更好的理由,否则vector容器都是最佳的选择。
原文地址:https://www.cnblogs.com/suzhou/p/3638970.html