250 likes | 393 Views
第十九章. STL-2. 回顾. 泛型程序设计 与标准模板库有关的概念和术语 C++ 标准模板库中的容器. 目标. 迭代器 函数对象 标准 C++ 库中的泛型算法. 迭代器. 迭代器是面向对象版本的指针 指针可以指向内存中的一个地址 迭代器可以指向容器中的一个位置 STL 的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。. begin(). end(). elem[0]. elem[1]. …. elem[n-1]. 迭代器的类型. 输入迭代器
E N D
第十九章 STL-2
回顾 • 泛型程序设计 • 与标准模板库有关的概念和术语 • C++标准模板库中的容器
目标 • 迭代器 • 函数对象 • 标准C++库中的泛型算法
迭代器 • 迭代器是面向对象版本的指针 • 指针可以指向内存中的一个地址 • 迭代器可以指向容器中的一个位置 • STL的每一个容器类模版中,都定义了一组对应的迭代器类。使用迭代器,算法函数可以访问容器中指定位置的元素,而无需关心元素的具体类型。 begin() end() elem[0] elem[1] … elem[n-1]
迭代器的类型 • 输入迭代器 • 可以用来从序列中读取数据 • 输出迭代器 • 允许向序列中写入数据 • 前向迭代器 • 既是输入迭代器又是输出迭代器,并且可以对序列进行单向的遍历 • 双向迭代器 • 与前向迭代器相似,但是在两个方向上都可以对数据遍历 • 随机访问迭代器 • 也是双向迭代器,但能够在序列中的任意两个位置之间进行跳转
#include <list> #include <iostream> using namespace std; int main(){ int i,key; list<int> intList; list<int>::iterator it; cout<<"input 5 digit:"; for(i=0;i<5;i++){ cin>>key; intList.push_front(key); } cout<<"data list:"<<endl; it=intList.end(); while(1){ cout.width(6); cout<<*(--it); if(it==intList.begin()) break; } return 0; } 迭代器的使用
函数对象 • 一个行为类似函数的对象,它可以没有参数,也可以带有若干参数,其功能是获取一个值,或者改变操作的状态。 • 任何普通的函数和任何重载了调用运算符operator()的类的对象都满足函数对象的特征 • STL中也定义了一些标准的函数对象,如果以功能划分,可以分为算术运算、关系运算、逻辑运算三大类。为了调用这些标准函数对象,需要包含头文件<functional>。
已集成的函数对象 可以自己编写一个函数作 为算法的参数
#include <iostream> using namespace std; class CFunObj{ public: void operator()(){ cout<<"hello,function object!"<<endl; } int operator()(int i){ cout<<"hello, function object other!"<<endl; return i+1; } private: int dat; }; void main(){ CFunObj fo; fo(); cout<<fo(1)<<endl; //CFunObj()(); } 自定义函数对象
标准C++库中的算法 • 算法本身是一种函数模板 • 不可变序列算法(non-mutating algorithms) • 不直接修改所操作的容器内容的算法 • 可变序列算法(mutating algorithms) • 可以修改它们所操作的容器的元素。 • 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成
STL算法的头文件 • <algorithm>是所有STL头文件中最大的一个,它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。 • <numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。 • <functional>中则定义了一些模板类,用以声明函数对象。
泛型算法例子3-1 #include <iostream> #include <vector> #include <algorithm> #include <iterator> #include <numeric> #include <functional> using namespace std; int main(){ int ia[] = { 1, 2, 3, 4, 5, 7, 9, 11 }; vector<int> iv(ia, ia+8); //累加,52 cout<<accumulate(iv.begin(),iv.end(),10)<<endl; //相邻差值 adjacent_difference(iv.begin(),iv.end(),iv.begin()); //复制到ostream_iterator 去, 每列印一个元素, 即加上一个空格
泛型算法例子3-2 copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”)); // 1 1 1 1 1 2 2 2 //计算元素值为2 的个数 cout << count(iv.begin(), iv.end(), 2) << endl; // 3 //计算奇数元素的个数 cout << count_if(iv.begin(), iv.end(), bind2nd(modulus<int>(),2)) << endl; // 5 //从头开始填入新值7, 填3 次 fill_n(iv.begin(), 3, 7); copy(iv.begin(), iv.end(), ostream_iterator<int>(cout,“ ”)); // 7 7 7 1 1 2 2 2 //内积, 7*7 + 7*7 + 7*7 + 1*1 + 1*1 + 2*2 + 2*2 + 2*2 cout << inner_product(iv.begin(), iv.end(), iv.begin(),0) << endl; //161
泛型算法例子3-3 //排序 sort(iv.begin(), iv.end()); copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”)); // 1 1 2 2 2 7 7 7 //顛倒元素次序 reverse(iv.begin(), iv.end()); copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”)); // 7 7 7 2 2 2 1 1 //旋转, 交换[first, middle)和[middle, last) rotate(iv.begin(), iv.begin()+3, iv.begin()+6); copy(iv.begin(), iv.end(), ostream_iterator<int>(cout, “ ”)); // 2 2 2 7 7 7 1 1 }
#ifndef CMYCLASS_H #define CMYCLASS_H #include <string.h> class CMyClass{ public: CMyClass(); CMyClass(string name,int age); friend bool Less(const CMyClass &num,const CMyClass &myclass); bool operator==(const CMyClass &myclass); string &GetName(); int GetAge(); private: string m_name; int m_age;};#endif CMyClass::CMyClass(){ m_name=""; m_age=12; } CMyClass::CMyClass(string name,int age) { m_name=name; m_age=age; } bool CMyClass::operator==(const CMyClass &myclass){ return m_name==myclass.m_name; } string & CMyClass::GetName(){ return m_name;} int CMyClass::GetAge(){ return m_age;} 自定义函数作为算法参数3-1
自定义函数作为算法参数3-2 #include "MyClass.h" #include <iostream> #include <algorithm> #include <vector> #include <functional> #include <numeric> using namespace std; bool Less(const CMyClass &num,const CMyClass &myclass){ return num.m_name<myclass.m_name; } void PrintMyClass(CMyClass &myclass){ cout<<"name:"<<myclass.GetName()<<"\t age:"<<myclass.GetAge()<<endl; } bool SearchByName(CMyClass &myclass){ return myclass.GetName()=="AAAAZ"; }
自定义函数作为算法参数3-3 void main(){ CMyClass myclass; vector<CMyClass> vec; vec.push_back(CMyClass("AAAA",12)); vec.push_back(CMyClass("DFKASDF",12)); vec.push_back(CMyClass("ASDFSAFA",12)); vec.push_back(CMyClass("Z",12)); vec.push_back(CMyClass("AAAAZ",12)); vec.push_back(CMyClass("DFKSADFZ",12)); sort(vec.begin(),vec.end(),Less); // for (vector<CMyClass>::iterator it=vec.begin();it!=vec.end();it++){ // cout<<it->GetName()<<endl;} for_each(vec.begin(),vec.end(),PrintMyClass); vector<CMyClass>::iterator r=find_if(vec.begin(),vec.end(),SearchByName); cout<<(*r).GetName()<<endl; }
总结 • 迭代器 • 函数对象 • 标准C++库中的算法 • 自定义函数作为算法参数