容器库概览
一般来说,每个容器都定义在一个头文件中,文件名与类型名相同。即,deque定义在头文件deque中,list定义在头文件list中,以此类推。
容器均定义为模板类。例如对vector,我们必须提供额外信息来生成特定的容器类型.对大多数,但不是所有容器,我们还需要额外提供元素类型信息:
list<Sales data>// 保存Sales_data对象的list
deque<double>// 保存double的deque
对容器可以保存的元素类型的限制
顺序容器几乎可以保存任意类型的元素。特别是,我们可以定义一个容器,其元素的类型是另一个容器。这种容器的定义与任何其他容器类型完全一样:在尖括号中指定元素类型(此种情况下,是另一种容器类型):
vector<vector<string>> lines;
// vector的vector此处lines是一个vector,其元素类型是string的vector。
较旧的编译器可能需要在两个尖括号之间键入空格,例如,
vector<vector<string> >
虽然我们可以在容器中保存几乎任何类型,但某些容器操作对元素类型有其自己的特殊要求。我们可以为不支持特定操作需求的类型定义容器,但这种情况下就只能使用那些没有特殊要求的容器操作了。
例如,顺序容器构造函数的一个版本接受容器大小参数,它使用了元素类型的默认构造函数。但某些类没有默认构造函数。我们可以定义一个保存这种类型对象的容器,但我们在构造这种容器时不能只传递给它一个元素数目参数:
//假定noDefault是一个没有默认构造函数的类型
vector<noDefault> v1(10, init);//正确:提供了元素初始化器
vector<noDefault> v2(10);// 错误:必须提供一个元素初始化器
当后面介绍容器操作时,我们还会注意到每个容器操作对元素类型的其他限制
所有容器都支持的容器操作
容器类型上的操作形成了一种层次:
- 某些操作是所有容器类型都提供的)。
- 另外一些操作仅针对顺序容器、关联容器或无序容器。
- 还有一些操作只适用于一小部分容器。
在本文中,我们将介绍对所有容器都适用的操作。
iterator | 此容器类型的迭代器类型 |
const_iterator | 可以读取元素,但不能修改元素的迭代器类型 |
size_type | 无符号整数类型,足够保存此种容器类型最大可能容器的大小 |
difference_type | 带符号整数类型,足够保存两个迭代器之间的距离 |
value_type | 元素类型 |
reference | 元素的左值类型;与value_type&含义相同 |
conat_reference | 元素的const左值类型(即,const value_type&) |
C c; | 默认构造函数,构造空容器(array除外,array是非空) |
C c1(c2); | 构造c2的拷贝c1 |
C c(b,e); | 构造c,将迭代器b和e指定的范围内的元素拷贝到c(array不支持) |
C c{a,b..}; | 列表初始化c |
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 |
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 |
reverse_iterator | 按逆序寻址元素的迭代器 |
const_reverse_iterator | 不能修改元素的逆序迭代器 |
c.rbegin(),,c.rend() | 返回指向c的尾元素和首元素之前位置的迭代 |
c.crbegin(),c.crend() | 返回const_reverse_iterator |