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<algorithm>
#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<algorithm>
#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<vector>
#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<vector>
#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中,期待中……

博爱声明: 

本文档在《博爱协议(版本一)》下授权,更多内容请查看:博爱
请关心支持人类的慈善事业,把爱与帮助给予需要她们的儿童与贫困家庭。
请关注如下站点:
联合国儿童基金会 | 中华慈善总会

posted @ 2012-08-23 17:54  Leo Forest  阅读(1117)  评论(0编辑  收藏  举报