for_each简单使用【转】
原文:http://cpp.ezbty.org/content/science_doc/c%E6%A0%87%E5%87%86%E5%BA%93%EF%BC%9A%E4%BD%BF%E7%94%A8_stdfor_each
我们先来看看std::for_each最简单和直接的用法,接着关注一下std::for_each更多创造性的用法。这个简单而直接的例子首先定义一个函数对象类型,然后调用std::for_each对一个迭代器组进行遍历操作。
#include<vector>
//新建一个函数对象的类型,它有一个定义好的函数操作符
struct OP
{
OP():s(0){}
void operator()(int& v)
{
v=s++;
}
private:
int s;
};
//初始化一个向量,它有10个整数
std::vector<int> vec(10);
//把向量10个整数分别设置从 0-9
std::for_each(vec.begin(), vec.end(), OP());
看了这个代码大家自然地产生了一个疑问,就是只是把向量里10元素设置一下值,为什么为直接使用一个for循环,而要如此费力地使用for_each,并且还要自己定义一个新的类型,这多难受。不错,就上面的例子使用for循环明显有优势,代码里也要显著减少。所以依常规方式使用for_each很多时候并不一定有更优秀的代码,这也是for_each等STL算法一直都难以被大量应用的一个原因:尽管功能强大,但使用不方便。有许多尝试和努力来解决这一不方便,从而STL算法真正成为方便可用的工具。
STL预定义的函数对象和函数适配器
使用不方便在STL设计之初就已经被认识,所以STL专门提供了一些简化使用设施,这就是预定义的函数对象和函数适配器。这些函数对象和函数适配器对简化算法调用直到一定的作用,关于它的更多内容请参看这里。
下面给出一个使用STL函数对象与适配器一个示例,由于这些设施功能仍然简陋,所以不能轻易实现上例的功能,此处的示例是把10个元素都同时加1:
#include<fuctional>
#include<vector>
std::for_each(vec.begin(), vec.end(),
std::bind1st(std::plus<int>(), 1));//参数绑定和执行加法
boost库对STL扩展:bind和lambda
boost对STL进行了很大扩展,并且这种扩展仍然在进行着。在上面的例子中我们看到一个std::bind1st函数,现在boost库对其进行的扩展,使得boost::bind可以做更多的事,同时语法也更统一。boost::lambda 则走得更远,它实际上是使用库的形式实际著名的lambda表达式,也就是“就地”小函数,它让我们定义一个简单而直观的函数变得异常容易,如此诸如std::for_each的算法需要的函数对象也就是更容易做到了。下面使用boost库来实现最初那个示例,你将看到它是如此得简单:
#include<algorithm>
#include<boost/lambda/lambda.hpp>
std::vector<int> vec;
{
using namespace boost::lambda;
int s=0;
std::for_each(vec.begin(), vec.end(), (_1=s, ++s));
// 或者也可以
std::for_each(vec.begin(), vec.end(), _1=var(s)++);
}
看到如此精致代码是否已心动,更多内容可以参数boost::lambda库文档(中文)。
C++0x(下一代C++)的努力:语言级lambda
lambda表达式实际上是函数式语言的核心,理论上说它现在现有的各种语言都可以构成等价。大家可能知道冯诺依曼机,在历史上lambda与冯诺依曼机是等价的。是现代计算机理论的3个源头之一。它如此重要,所以在下一代C++标准里已经把它加入核心语言,如此我们就不再需要boost::lambda库了。下面示例C++0x中最初示例的样子,它在GCC 4.5.1中编译并运行正确。
#include<algorithm>
#include<iostream>
#include<iterator>
int main()
{
std::vector<int> vec(10);
int s=0;
std::for_each(vec.begin(), vec.end(), [&s](int& a){ a=s++; });
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout));
}
现在可以看出来就简单的方法原来在C++0x中,期待中……