第八周 标准模板库STL(一)
1.string类
2.标准模板库STL概述(一)
3.标准模板库STL概述(二)
4.vector,deque和list
5.函数对象
函数对象
如果一个类重载了运算符“()”,则该类的对象就都是函数对象。函数对象也是对象,但是用起来看上去和函数非常像,实际上是执行了成员函数的调用。
class CMyAverage {
public:
double operator()( int a1, int a2, int a3 ) {//重载 () 运算符
return (double)(a1 + a2+a3) / 3;
}
};
CMyAverage average; //函数对象
cout << average(3,2,3); // average.operator()(3,2,3), 用起来看上去象函数调用 输出 2.66667
函数对象的应用
STL里有以下对一个区间操作的模板:
template<class InIt, class T, class Pred>
T accumulate(InIt first, InIt last, T val, Pred pr);
pr 就是个函数对象,pr也可以是个函数。
对[first,last)中的每个迭代器 I,执行 val = pr(val,* I) ,返回最终的val。
Dev C++ 中accumulate的源代码1:
template<typename _InputIterator, typename _Tp>// typename 等效于class
_Tp accumulate(_InputIterator __first, _InputIterator __last,_Tp __init)
{
for ( ; __first != __last; ++__first)
__init = __init + *__first;
return __init;
}
Dev C++ 中的 accumulate 源代码2:
template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
_Tp accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, _BinaryOperation __binary_op)
{
for ( ; __first != __last; ++__first)
__init = __binary_op(__init, *__first);
return __init;
}
//调用accumulate 时,和 __binary_op对应的实参可以是个函数名称、函数指针或函数对象。
函数例子:
#include
#include
#include
#include
#include
using namespace std;
int sumSquares( int total, int value){
return total + value * value;
}
template <class T>
void PrintInterval(T first, T last){ //输出区间[first,last)中的元素
for( ; first != last; ++ first)
cout << * first << " ";
cout << endl;
}
template<class T>
class SumPowers{
private:
int power;
public:
SumPowers(int p):power(p) { }
const T operator() ( const T & total,
const T & value){ //计算 value的power次方,加到total上
T v = value;
for( int i = 0;i < power - 1; ++ i)
v = v * value;
return total + v;
}
};
int main()
{
const int SIZE = 10;
int a1[] = { 1,2,3,4,5,6,7,8,9,10 };
vector<int> v(a1,a1+SIZE);
cout << "1) "; PrintInterval(v.begin(),v.end());
int result = accumulate(v.begin(),v.end(),0,SumSquares);
cout << "2) 平方和:" << result << endl;
result = accumulate(v.begin(),v.end(),0,SumPowers<int>(3));
cout << "3) 立方和:" << result << endl;
result = accumulate(v.begin(),v.end(),0,SumPowers<int>(4));
cout << "4) 4次方和:" << result;
return 0;
}
输出:
1) 1 2 3 4 5 6 7 8 9 10
2) 平方和: 385
3) 立方和: 3025
4) 4 次方和: 25333
原理
int result = accumulate(v.begin(),v.end(),0,SumSquares);
实例化出:
int ( * op)( int,int)表明定义了一个返回值为int,输入类型是两个int的函数指针
int accumulate(vector<int>::iterator first,vector<int>::iterator last, int init,int ( * op)( int,int))
{
for ( ; first != last; ++first)
init = op(init, *first);
return init;
}
int result = accumulate(v.begin(),v.end(),0,SumPowers(3));
实例化出:
SumPowers op表明op是一个函数对象
int accumulate(vector<int>::iterator first, vector<int>::iterator last, int init, SumPowers<int> op)
{
for ( ; first != last; ++first)
init = op(init, *first);
return init;
}
STL 中的函数对象类模板:
equal_to
greater
less …….
这些模板可以用来生成函数对象。
头文件:functional
greater 函数对象类模板
template<class T>
struct greater : public binary_function<T, T, bool> {
bool operator()(const T& x, const T& y) const {
return x > y;
}
};
这个greater的大小和数学上的大小正好是反过来的,降序。这点我不太懂。
binary_function定义:
template<class Arg1, class Arg2, class Result>
struct binary_function {
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
greater 的应用
list 有两个sort函数
void sort();前面例子中看到的是不带参数的sort函数,它将list中的元素按 < 规定的比较方法升序排列。
list还有另一个sort函数:
template <class Compare>
void sort(Compare op);
将list中的元素按op规定的比较方法升序排列。即要比较x,y的大小时,看op(x,y)的返回值,为true则认为x小于y,和简单的小于号还是有区别的。
#include
#include
#include
using namespace std;
class MyLess {
public:
bool operator()( const int & c1, const int & c2 ){
return (c1 % 10) < (c2 % 10);//谁的个位数小,谁就小
}
};
template <class T>
void Print(T first, T last){
for(;first != last;++first)
cout << *first << ",";
}
int main()
{
const int SIZE = 5;
int a[SIZE] = {5,21,14,2,3};
list<int> lst(a, a+SIZE);
lst.sort(MyLess());
Print(lst,begin(), lst.end());
cout << endl;
lst.sort(greater<int>()); //greater()是个对象,本句进行降序排序
Print(lst,begin(), lst.end());
return 0;
}
输出:
21,2,3,14,5,
21,14,5,3,2,
引入函数对象后,在STL中使用自定义的“大”,“小”关系
关联容器和STL中许多算法,都是可以用函数或函数对象自定义比较器的。在自定义了比较器op的情况下,以下三种说法是等价的:
例子:写出MyMax模板
#include
#include
using namespace std;
class MyLess{
public:
bool operator() (int a1,int a2){//谁的个位数小谁就小
if( ( a1 % 10 ) < (a2%10) )
return true;
else
return false;
}
};
bool MyCompare(int a1,int a2){//谁的个位数大谁就小
if( ( a1 % 10 ) < (a2%10) )
return false;
else
return true;
}
int main()
{
int a[] = {35,7,13,19,12};
cout << MyMax(a,5,MyLess()) << endl;
cout << MyMax(a,5,MyCompare) << endl;
return 0;
}
要输出:
19
12
则MyMax定义如下:
template <class T, class Pred>
T MyMax( T * p, int n, Pred myless){
T tmpmax = p[0];
for( int i = 1;i < n;i ++ )
if( myless(tmpmax,p[i]))
tmpmax = p[i];
return tmpmax;
};