<utility.h>utility中只有模版类pair,和一些与之相关联得模版操作符,该模版类用来将两个对象合并为一个对象,当你想要一个函数返回两个值得时就比较方便了。
其中模版函数make_pair可以在必要时产生一个pair对象,该函数在检测参数时忽略掉所有CONST属性,所以不能依赖他产生包含一个或多个常量成员对象得pair对象。
测试文件:
#include "iostream"#include "assert.h"#include "utility"using namespace std;
class Int{public: Int(int v):val(v){} Int(){val=0;} bool operator==(Int x)const{return (val==x.val);}//仅重载==AND<就可以了,其他的库会帮我们完成 bool operator<(Int x) const{return (val<x.val);} //重载函数private: int val;};
typedef pair<int ,char>pair_ic;pair_ic p0;
typedef pair<Int,char>pair_id;pair_id d0;
int main(){ pair_ic p1=p0,p2(3,'a'); assert(p1.first==0); assert(p1.second==0); assert(p2.first==3); assert(p2.second=='a'); assert(p2==make_pair((pair_ic::first_type)3,(pair_ic::second_type)'a')); assert(p2<make_pair((pair_ic::first_type)4,(pair_ic::second_type)'a')); assert(p2<make_pair((pair_ic::first_type)3,(pair_ic::second_type)'b')); assert(p1!=p2); Int a(2),b(3); pair_id d0(a,'a'); pair_id d1(a,'b'); assert(d0!=d1); assert(d0<=d1); assert(d1>=d0); return 0; }
<iterator> 中定义了迭代器得使用方法,主要得模版类有:
插入迭代器
插入迭代器是一种迭代器适配器,带有一个容器参数,并生成一个迭代器,用于在指定的容器中插入元素。通过插入迭代器赋值时,迭代器将会插入一个新的元素。C++语言提供了三种插入器,其差别在于插入元素的位置不同:
back_inserter,创建使用push_back实现插入的迭代器,其使用一个对象作为实参将一个新元素插入到容器得后端 front_inserter的操作类似于back_inserter:该函数将创建一个迭代器,调用它所关联的基础容器的push_front成员函数代替赋值操作。 注意:只有当容器提供push_front操作时,才能使用front_inserter。在vector或其他没有push_front运算的容器上使用front_inserter,将产生错误。 inserter使用insert实现插入操作,inserter还带有第二个实参:指向插入起始位置的迭代器,inserter总是在它的迭代器参数所标明的位置前面插入新元素。 流迭代器 虽然iostream类型不是容器,但标准库同样提供了在iostream对象上使用的迭代器:istream_iterator用于读取读入流,而ostream_iterator用于写输出流。这些迭代器将它们所对应的流视为特定类型的元素序列。使用流迭代器时,可以用泛型算法从流对象中读数据(或将数据写到流对象中)。 istream_iterator<T> in(strm); 创建从输入流strm中读取T类型对象的istream_iterator对象,strm是一个输入流 istream_iterator<T> in; istream_iterator对象的超出末端迭代器 ostream_iterator<T> out(strm); 创建将T类型的对象写到输出流strm的ostream_iterator对象 ostream_iterator<T> out(strm, delim); 创建将T类型的对象写到输出流strm的ostream_iterator对象,在写入过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组 流迭代器只定义了最基本的迭代器操作:自增、引用和赋值。此外,可比较两个istream迭代器是否相等(或不等)。而ostream迭代器则不提供比较运算。 流迭代器的限制: (1)不可能从ostream_iterator对象读入,也不可能写到istream_iterator对象中; (2)一旦给ostream_iterator对象赋了一个值,写入就提交了。赋值后,没有办法再改变这个值。此外,ostream_iterator对象中每个不同的值都只能正好输出一次。 (3)ostream_iterator没有->操作符。 测试:#include <iostream>#include <vector>#include <iterator>using namespace std;int main() { istream_iterator<int> in_iter(cin); istream_iterator<int> eof; //vector<int> vec(in_iter, eof); //do the same work as following loop vector<int> vec; while (in_iter != eof) vec.push_back(*in_iter++); //*in_iter可以取出输入流中得元素 vector<int>::const_iterator it = vec.begin(); for(; it != vec.end(); ++it) cout<<*it<<endl; return 0;}
#include <iostream>#include <iterator>using namespace std;int main() { ostream_iterator<string> out_iter(cout, "/n"); istream_iterator<string> in_iter(cin), eof; while (in_iter != eof) *out_iter++ = *in_iter++; return 0;}
反向迭代器 反向迭代器是一种反向遍历容器的迭代器。也就是,从最后一个元素到第一个元素遍历容器。反向迭代器将自增(和自减)的含义反过来了:对于反向迭代器,++运算将访问前一个元素,而--运算则访问下一个元素。 (1)反向迭代器需要使用自减操作符:标准容器上的迭代器(reverse_iterator)既支持自增运算,也支持自减运算。但是,流迭代器由于不能反向遍历流,因此流迭代器不能创建反向迭代器。 (2)可以通过reverse_iterator::base()将反向迭代器转换为普通迭代器使用,从逆序得到普通次序。 测试: #include <iostream>#include <string>#include <iterator>#include <algorithm>using namespace std; int main() { string str = "this 'sentence' is a test"; cout<<str<<endl; string::iterator it1 = find(str.begin(), str.end(), '/''); string::iterator it2 = find(++it1, str.end(), '/''); cout<<string(it1, it2)<<endl; string::reverse_iterator rit1 = find(str.rbegin(), str.rend(), '/''); string::reverse_iterator rit2 = find(++rit1, str.rend(), '/''); cout<<string(rit1, rit2)<<endl; cout<<string(rit2.base(), rit1.base())<<endl; getchar(); return 0;} 不同的迭代器支持不同的操作集,而各种算法也要求相应的迭代器具有最小的操作集。因此,可以将算法的迭代器分为下面五类: 输入迭代器(input iterator) 读,不能写。支持的操作集:==, !=, 前缀++, 后缀++, *, ->。例如,find, accumulate算法要求这类迭代器。 输出迭代器(output iterator) 写,不能读。支持的操作集:前缀++, 后缀++, *(只能出现在赋值运算的左操作数上)。推出迭代器要求每个迭代器必须正好写入一次。例如,ostream_iterator是输出迭代器,copy算法使用这类迭代器。 前向迭代器(forward iterator) 读和写,支持输入迭代器和输出迭代器提供的所有操作,还支持对同一个元素的多次读写。例如,replace算法需要这种迭代器。 双向迭代器(bidirectional iterator) 读和写,除了支持前向迭代器的所有操作,还支持前缀--和后缀--,即支持双向遍历容器。例如,reverse算法要求这类迭代器。标准库容器中提供的迭代器都至少达到双向迭代器的要求。 随机访问迭代器(random-access iterator) 读和写。提供在常量时间内访问容器任意位置的功能。支持完整的迭代器操作集:1)关系运算:==, !=, <, <=, >, >=;2)算术运算:it + n, it - n, it += n, it -= n以及it1 - it2;3)下标运算:it[n],等价于*(it + n)。需要随机访问迭代器的泛型算法包括sort算法。例如,vector, deque, string迭代器是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。 除了输出迭代器,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方,可使用任意一种更高级的迭代器。例如,对于需要输入迭代器的算法,可传递前向、双向或随机访问迭代器调用该算法。而反之则不行。注意:向算法传递无效的迭代器类别所引起的错误,无法保证会在编译时被捕获到。 map, set, list类型提供双向迭代器,而string, vector和deque容器上定义的迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator是输入迭代器,ostream_iterator是输出迭代器。 另外,虽然map和set类型提供双向迭代器,但关联容器只能使用这部分算法的一个子集。因为关联容器的键是const对象。因此,关联容器不能使用任何写序列元素的算法。只能使用与关联容器绑在一起的迭代器来提供用于读操作的实参。因此,在处理算法时,最好将关联容器上的迭代器视为支持自减运算的输入迭代器,而不是完整的双向迭代器。
<memory> 它以不同寻常得方式为容器中得元素分配存储空间,它同样也为某些算法执行期间产生得临时对象提供机制,主要模版类为:allocator由他产生容器得默认分配器,我们很少需要直接与分配器打交道,默认得分配器已经可以很好得为我们工作了,但它又包含在标准C++库中所定义得每个容器模版类得模版参数里。