定义一个顺序容器
为了定义一个容器对象 ,我们必须先包含相关联的头文件, 应该是下列头文件之一
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
容器对象的定义以容器类型的名字开始 ,后面是所包含的元素的实际类型,例如
vector< string > svec;
list< int > ilist;
定义了 svec 是一个内含 string 对象的主 vector, 以及 ilist 是一个 int 型对象的空 list。 svec和 ilist 都是空的。为了确认这一点, 我们可以调用 empty()操作符 ,例如:
if ( svec.empty() != true )
; // 喔, 有错误了
插入元素最简单的方法是 push_back() ,它将元素插入在容器的尾部 。例如:
string text_word;
while ( cin >> text_word )
svec.push_back( text_word );
每次从标准输入读取一个字符串放到 text_word 中, 然后 push_back()再将 text_word 字符串的拷贝插入到 svec 中。 list 和 deque 容器也支持 push_front(), 它把新元素插入在链表的前端, 例如 :假设我们有一个 int 型的内置数组如下:
int ia[ 4 ] = { 0, 1, 2, 3 };
用 push_back():
for ( int ix = 0; ix < 4; ++ix )
ilist.push_back( ia[ ix ] );
创建序列 0 1 2 3 然而 如果使用 push_front():
for ( int ix = 0; ix < 4; ++ix )
ilist.push_front( ia[ ix ] );
则在 ilist 中创建序列 3 2 1 0
另外 ,我们或许希望为容器指定一个显式的长度, 长度可以是常量, 也可以是非常量表达式:
#include <list>
#include <vector>
#include <string>
extern int get_word_count( string file_name );
const int list_size = 64;
list< int > ilist( list_size );
vector< string > svec(get_word_count(string("Chimera")));
注:
如果一个 C++编译器不支持缺省模板参数, 那么它要求第二个实参指定分配器 (allocator)。 在这样的编译器实现下 ,上述两个定义被声明如下list< int > ilist( list_size, - 1 ); vector< string > svec( 24, "pooh" );
allocator 类封装了分配和删除动态内存的抽象过程, 它也是标准库预定义的类. 实际上它使用了 new 和 delete操作符 ,使用这样的分配器类有两个目的 :通过把容器与内存分配策略的细节分开, 这可以简化容器类的实现 ;其次, 程序员有可能实现或者指定其他的内存分配策略, 比如使用共享内存.
如果容器的主要行为是在前端插入元素 则 deque 比 vector 的效率高 所以我们应该优先选择 deque
容器中的每个元素都被初始化为与该类型相关联的缺省值 。对于整数 :将用缺省值0 初值化所有元素。 对于 string 类 :每个元素都将用 string 的缺省构造函数初始化。
除了用相关联的初始值来初始化每个元素外 ,我们还可以指定一个值 ,并用它来初始化每个元素。
例如:
list< int > ilist( list_size, - 1 );
vector< string > svec( 24, "pooh" );
除了给出初始长度外 ,我们还可以通过 resize()操作重新设置容器的长度。 例如 ,当我们
写下面的代码时:
svec.resize( 2 * svec.size() );
我们将 svec 的长度加了一倍 ,每个新元素都被初始化为 与元素底层类型相关联的缺
省值 。
如果我们希望把每个新元素初始化为某个其他值, 则可以把该值指定为第二个参
数:
// 将新元素初始化为 piglet
svec.resize( 2 * svec.size(), "piglet" );
那么 svec 的原始定义的容量是多少 ?它的初始长度是 24 个元素 。
它的初始容量可能是多少? 对——svec 的容量也是 24 。
一般地, vector 的最小容量是它的当前长度, 当 vector的长度加倍时 ,容量一般也加倍。
我们也可以用一个现有的容器对象 初始化一个新的容器对象 。例如:
vector< string > svec2( svec );
list< int > ilist2( ilist );
每个容器支持一组关系操作符 ,我们可以用来比较两个容器 。这些关系操作符分别是:
等于 、不等于 、小于 、大于、 小于等于、大于等于
容器的比较是指两个容器的元素之间成对进行比较 。如果所有元素相等而且两个容器含有相同数目的元素 ,则两个容器相等,否则 ,它们不相等。 第一个不相等元素的比较决定了两个容器的小于或大于关系 。
例如 ,下面是一个程序的输出 ,它比较了五个 vector:
ivec1: 1 3 5 7 9 12
ivec2: 0 1 1 2 3 5 8 13
ivec3: 1 3 9
ivec4: 1 3 5 7
ivec5: 2 4
// 第一个不相等元素: 1, 0
// ivec1 大于 ivec2
ivec1 < ivec2 // flase
ivec2 < ivec1 // true
// 第一个不相等元素: 5, 9
ivec1 < ivec3 // true
// 所有元素相等, 但是, ivec4 的元素少
// 所以 ivec4 小于 ivec1
ivec1 < ivec4 // false
// 第一个不相等元素: 1, 2
ivec1 < ivec5 // true
ivec1 == ivec1 // true
ivec1 == ivec4 // false
ivec1 != ivec4 // true
ivec1 > ivec2 // true
ivec3 > ivec1 // true
ivec5 > ivec2 // true
我们能够定义的容器的类型有三个限制 。实际上, 它们只适用于用户定义的类类型
- 元素类型必须支持等于操作符
- 元素类型必须支持小于操作符 ,前面讨论的所有关系操作符都用这两个操作符来实现
- 元素类型必须支持一个缺省值 ,对于类类型 ,即指缺省构造函数
所有预定义数据类型 ,包括指针 ,都满足这些限制。 C++标准库给出的所有类类型也一样