关于容器的头文件
一般来说,存在一些对所有容器都适用的操作,**每个容器都定义在一个头文件中,文件名即deque定义在头文件<deque>,list定义在头文件<list>中,以此类推。
对容器可以保存的元素的类型的限制
顺序容器几乎可以保存任意类型的元素,特别是,我们可以定义一个容器,容器中的元素可以是另一个容器,这种类型的定义与任何其他容器类型完全一样,如:(需要注意的是,在比较旧的编译器可能需要在后面的两个尖括号中键入空格)
vector<vector<string>>v;
需要注意的是:有些容器没有提供默认构造函数,那么我们使用这种“”容器的容器“时,就需要为每个外层容器的每个元素提供参数,比如:
vector<nodefult> v(10,init)
nodefult是一个不提供默认构造函数的类型,那么我们在定义容器时,就需要为每个容器提供参数,否则就会出错
迭代器
关于迭代器的类型,拥有迭代器的标准库迭代器类型为iterator和const_iterator,后者表示只读。
与容器一样,迭代器有着公共的接口,如果一个迭代器提供某个操作,那么所有提供相同操作的迭代器对这个操作的实现方式都相同
迭代器范围
一个迭代器范围是由一对迭代器表示,两个迭代器分别指向同一个容器中的元素或者是尾元素之后的位置,这两个迭代器通常被称为begin和end,他们标记了容器中元素的一个范围
迭代器范围中的元素包含begin所表示的元素以及begin开始直至end(不包括end)之间的所有元素,这种元素范围被称为左闭合区间,表示为[begin,end)
迭代器所蕴含的编程假定
使用左闭合范围蕴含的编程假定
- 如果begin和end相等,则范围为空
- 如果begin和end不等,则范围至少包含一个元素
- 我们可以对begin递增若干次,使得begin==end
容器类型成员
类型别名 | 表示的意思 |
---|---|
iterator | 此容器类型的迭代器类型 |
const_iterator | 可以读取元素,但是不能修改元素的迭代器类型 |
size_type | 无符号类型,足够保存此种容器类型最大可能容器的大小 |
difference_type | 带符号整数类型,足够保存两个迭代器之间的距离 |
value_type | 元素类型 |
reference | 元素的左值,与value_type含义相同 |
例如:
list<string> ::iterator ite
ite是通过list<string>定义的一个迭代器类型
begin和end成员
begin和end操作生成指向容器中第一个元素和尾元素之后位置的迭代器,这两个迭代器最常见的用途是形成一个含容器中所有元素的迭代器范围,一般将auto和begin或end结合使用,此时获得的迭代器类型依赖于容器类型,与我们想要如何使用迭代器毫不相干,如:
auto it7=a.begin();
auto it8=a.cbegin();
仅当a是const时,it7才是const_iterator,但是it8永远是const_iterator类型
当不需要写访问时,应使用cbegin和cend
容器的定义和初始化
- 每个容器类型都定义了一个默认的构造函数,除array容器外,其他容器的默认构造参数都会创建一个空的容器(array容器类型因为是固定大小的容器,所以在默认初始化时需要提供容器大小)
- 只有顺序容器的构造函数才能接受大小参数
- 为了创建一个容器为另外一个容器的拷贝,两个容器的类型和元素的类型必须要相匹配,但是当传递迭代器参数来拷贝一个范围时,就不要求容器类型相同,而且,新容器和原容器中的元素类型也可以不同,只要能将拷贝的元素转换
- 需要谨记的是:当一个容器初始化为另外一个容器的拷贝时,两个容器的容器类型和元素类型要相同
- 我们可以使用迭代器拷贝一个子序列,两个迭代器分别标记想要拷贝的第一个元素和尾元素之后的位置
- 顺序容器(array除外)还提供了另一个构造函数,它接受一个容器大小和一个(可选的)元素初值,如果我们不提供初值,则标准库会创建一个值初始化器。
- 关于array的初始化
- 与内置数组一样,标准库array的大小也是类型的一部分,当定义一个array时,除了指定元素类型外,还要指定容器大小,为了使用array类型,我们必须同时指定元素类型和大小。
- 如果我们对array进行列表初始化,那么初始化的数目必须等于或者小于array的大小,如果初始化的数目小于array大小,则靠前的元素被初始化,剩余的元素都会进行值初始化
- 我们不能对内置数组进行拷贝或者对象赋值操作,但array并没有这个限制,只要初始值的类型与要创建的容器类型相等,还有元素类型和容器大小也要相等
赋值和swap
- 赋值操作(=)将其左边容器中的全部元素替换为右边容器中元素的拷贝,如果两个容器大小不相等,赋值操作之后两者的大小都与右边容器相等。
- array类型不支持arrign,也不允许用花括号包围的值列表进行赋值,例如下式,这是错误的,使用花括号进行赋值操作是在定义时使用的。
array\<int> a;
a={0};
- 顺序容器还定义了一个名为assign的成员,允许我们从一个不同但是相容的类型赋值,或者从容器的一个子序列赋值,assign操作用参数所指定的元素替换左边容器中的所有元素需要注意的是,由于其旧元素被替换,因此传递给assign的迭代器不能指向assign的容器,assign的第二个版本接受一个整型值和一个元素值,它用于指定数目且具有相同给定值的元素替换容器中的原有元素
使用swap
- swap操作将会交换两个相同类型容器中的内容。调用swap后,两个容器中的元素将会交换
- 除array外,交换两个容器内容的操作会很快,因为元素本身并未交换,swap只是交换了两个容器的内部数据结构,具体一步来说,交换容器的数据结构是指:交换容器元素的内存地址,并不是元素所存储的值,元素不会移动的事实表明,除string外,指向容器的迭代器,引用和指针在swap操作之后并未失效,他们仍指向swap操作之前的那些元素,但是,在swap之后,这些元素已经属于不同的容器了,需要注意的是,对string调用swap会导致迭代器,引用和指针失效
- swap两个array会真正交换他们的元素,因此,交换两个array所需的时间与array中的元素数目成正比