1. 顺序容器
1.1 容器的定义和初始化
除array外,容器的默认构造函数都会创建一个指定类型的空容器,切都可以接受指定元素大小和元素初始值的参数。
我们可以将一个容器初始化为另一个容器的拷贝:直接拷贝容器,或拷贝由一个迭代器指定的元素范围。直接拷贝容器,需要两个容器的类型和元素的类型都匹配,不过使用迭代器范围拷贝就不要求容器类型相同了。
顺序容器提供了接收一个容器大小和一个(可选的)元素初始值的构造函数,若不提供初始值,则该元素的类型应该为内置类型或者具有默认构造函数的类类型。
1.2 赋值
容器可以直接执行赋值操作:
c1 = c2; //将c1的内容替换为c2的内容
如果我们想要复制一段范围,可以使用assign函数:
c1.assign(c2.begin(),c2.end());
c1.assign(10,"test");
c1.swap(c2);
swap(c1,c2);
使用swap交换元素会非常的高效,可在常数事件内完成,因为两个容器内部的元素实际并未交换,只是交换了两个容器内部的数据结构。由于元素并未移动,因此指向容器的迭代器,引用和指针都不会失效,尽管这些元素已经属于别的容器(string容器除外)。
容器提供了三个有关大小的操作接口:size() 返回容器中的元素数目;empty()判断容器是否为空;max_size()返回该容器锁容纳的最大元素数。不过forward_list是不支持size的。
每个容器都提供了相等运算符,即” = “ 和 ”!=",除了无序关联容器外都支持关系运算法,不过运算符左右两端必须是相同类型的容器,且必须保存相同类型的元素。实际上,比较两个容器比较的是容器内部元素的逐对比较,其准则与string的关系运算类似。
2. 顺序容器操作
2.1 向容器内添加元素
顺序容器可以支持有insert、push_back、push_front、emplace(新标准中的)等添加元素的接口(不同容器支持的操作不同)。向vector、string或者deque插入元素会使所有指向容器的迭代器、引用和指针失效。
当我们用一个对象来初始化容器,或将一个对象插入到容器中时,实际上存放的是一个对象的拷贝,而不是对象本身。
push_back,在容器末尾添加数据,以下是两个例子:
string word;
while(cin >> word)
container.push_back(word);
word.push_back('c');//string实际上就是一个字符容器
push_front,在容器的头部插入数据;
insert,在指定位置的前方插入数据,或同时插入多个数据,insert的返回值是指向当前插入的元素的迭代器:
slist.insert(iter, "hello!");
slist.insert(slist.end(),10,"Anna");
slist.insert(slist.end(),svector.begin(),svector.end());
2.2 访问元素
大部分的顺序容器都支持下标访问的方式,但编译器实际上不会做越界检查,如果我们希望下标是合法的,可以使用at成员函数,当发生越界时,at会抛出一个out_of_range异常。
在使用front 和 back访问容器时,必须保证容器非空。
我们通过pop_front 和pop_back也可以访问容器,不过与front和back不同,这两个操作时破坏性的,即会在访问时删除对应元素。相当于同时执行了front和erase操作。
使用clear函数可以清空元素。
我们还可以动态的改变容器的大小:
c.resize(n);//若n小于size则丢弃多出的部分
c.resize(n,t);//任何新添加的元素都初始化为t
管理容量的函数
c.capacity();//返回容器c的容量
c.reserve(n);//分配至少容纳n个元素的空间
reserve永远不会改变容器占用的内容空间,resize永远只改变容器内元素的数目,而不是容器的容量。capacity和size的区别在于,capacity指出容器不改变大小的情况下可以存储多少元素,而size标明容器已经存放了多少元素。
实际上,vector对内存分配采用如下的策略:每次需要分配新内存空间时都将当前的容量翻倍。
4. string的一些操作
当我们使用const char* 创建string对象时,指针指向的数组必须以‘\0'作为结尾。
取子串操作:sbustr
string s("hello world");
string s2 = s.substr(0,5); //s2 = "hello"
string s3 = s.substr(6); //s3 = "world"
string s4 = s.substr(12); //out_of_range异常
s.substr(pos,n);//函数原型,实际上n表示取多少个字符
改变string的一些方法:insert,erase,append,replace
搜索操作:
find函数可以完成最简单的搜索,如果找到返回首字符的索引,如果没有找到则返回string::npos,其初始值为-1.
5.容器适配器
标准库定义了三个顺序容器适配器:stack、queue、priority_queue。默认情况下,前两者是基于deque实现的,而后者是基于vector实现的。
每个适配器都定义了两个构造函数:默认构造函数创建一个空对象,接受一个容器的构造函数拷贝该容器来初始化适配器。