30分钟掌握STL系列(五)

来源:互联网 发布:网络教育高升本费用 编辑:程序博客网 时间:2024/04/28 12:28

                                                                                                                             30分钟掌握STL系列(五)

这一节讲一讲STL中的函数与函数对象。

STL中,函数被称为算法,也就是说它们和标准C库函数相比,它们更为通用。STL算
法通过重载operator()函数实现为模板类或模板函数。这些类用于创建函数对象,对
容器中的数据进行各种各样的操作。下面的几节解释如何使用函数和函数对象。

函数和断言
经常需要对容器中的数据进行用户自定义的操作。例如,你可能希望遍历一个容器中
所有对象的STL算法能够回调自己的函数。例如

#i nclude <iostream.h>
#i nclude <stdlib.h> // Need random(), srandom()
#i nclude <time.h> // Need time()
#i nclude <vector> // Need vector
#i nclude <algorithm> // Need for_each()

#define VSIZE 24 // Size of vector
vector<long> v(VSIZE); // Vector object

// Function prototypes
void initialize(long &ri);
void show(const long &ri);
bool isMinus(const long &ri); // Predicate function

int main()
{
srandom( time(NULL) ); // Seed random generator

for_each(v.begin(), v.end(), initialize);//调用普通函数
cout << "Vector of signed long integers" << endl;
for_each(v.begin(), v.end(), show);
cout << endl;

// Use predicate function to count negative values
//
int count = 0;
vector<long>::iterator p;
p = find_if(v.begin(), v.end(), isMinus);//调用断言函数
while (p != v.end()) {
count++;
p = find_if(p + 1, v.end(), isMinus);
}
cout << "Number of values: " << VSIZE << endl;
cout << "Negative values : " << count << endl;

return 0;
}

// Set ri to a signed integer value
void initialize(long &ri)
{
ri = ( random() - (RAND_MAX / 2) );
// ri = random();
}

// Display value of ri
void show(const long &ri)
{
cout << ri << " ";
}

// Returns true if ri is less than 0
bool isMinus(const long &ri)
{
return (ri < 0);
}

所谓断言函数,就是返回bool值的函数。

函数对象
除了给STL算法传递一个回调函数,你还可能需要传递一个类对象以便执行更复杂的
操作。这样的一个对象就叫做函数对象。实际上函数对象就是一个类,但它和回调函
数一样可以被回调。例如,在函数对象每次被for_each()或find_if()函数调用时可
以保留统计信息。函数对象是通过重载operator()()实现的。如果TanyClass定义了
opeator()(),那么就可以这么使用:

TAnyClass object; // Construct object
object(); // Calls TAnyClass::operator()() function
for_each(v.begin(), v.end(), object);
STL定义了几个函数对象。由于它们是模板,所以能够用于任何类型,包括C/C++固有
的数据类型,如long。有些函数对象从名字中就可以看出它的用途,如plus()和multipl
ies
()。类似的greater()和less-equal()用于比较两个值。

 
注意
有些版本的ANSI C++定义了times()函数对象,而GNU C++把它命名为multiplies()。
使用时必须包含头文件<functional>。

一个有用的函数对象的应用是accumulate() 算法。该函数计算容器中所有值的总和
。记住这样的值不一定是简单的类型,通过重载operator+(),也可以是类对象。

//accum.cpp
#i nclude <iostream.h>
#i nclude <numeric> // Need accumulate()
#i nclude <vector> // Need vector
#i nclude <functional> // Need multiplies() (or times())

#define MAX 10
vector<long> v(MAX); // Vector object

int main()
{
// Fill vector using conventional loop
//
for (int i = 0; i < MAX; i++)
v[i] = i + 1;

// Accumulate the sum of contained values
//
long sum =
accumulate(v.begin(), v.end(), 0);
cout << "Sum of values == " << sum << endl;

// Accumulate the product of contained values
//
long product =
accumulate(v.begin(), v.end(), 1, multiplies<long>());//注意这行
cout << "Product of values == " << product << endl;

return 0;
}
编译输出如下:

$ g++ accum.cpp
$ ./a.out
Sum of values == 55
Product of values == 3628800
『注意使用了函数对象的accumulate()的用法。accumulate() 在内部将每个容器中
的对象和第三个参数作为multiplies函数对象的参数,multiplies(1,v)计算乘积。VC
中的这些模板的源代码如下:
// TEMPLATE FUNCTION accumulate
template<class _II, class _Ty> inline

_Ty accumulate(_II _F, _II _L, _Ty _V)

{for (; _F != _L; ++_F)

_V = _V + *_F;

return (_V); }

// TEMPLATE FUNCTION accumulate WITH BINOP

template<class _II, class _Ty, class _Bop> inline

_Ty accumulate(_II _F, _II _L, _Ty _V, _Bop _B)

{for (; _F != _L; ++_F)

_V = _B(_V, *_F);

return (_V); }

// TEMPLATE STRUCT binary_function

template<class _A1, class _A2, class _R>

struct binary_function {

typedef _A1 first_argument_type;

typedef _A2 second_argument_type;

typedef _R result_type;

};

// TEMPLATE STRUCT multiplies

template<class _Ty>

struct multiplies : binary_function<_Ty, _Ty, _Ty> {

_Ty operator()(const _Ty& _X, const _Ty& _Y) const

{return (_X * _Y); }

};

原创粉丝点击