打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C++标准库:使用 std::for_each

 

摘要:C++标准库里提供了多种算法,这些算法可以简化我们工作,可是这些算法都会需要一个函数对象作为其参数,有时又会不方便。本文讲述最重要也是最基础的算法std::for_each算法,它遍历一个序列,并执行一个操作,同时本文也讲述如何使得创建函数对象更方便快捷。

for_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中,期待中……

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
STL介绍
Boost:managed
C 23:下一个 C 标准
c++ vector删除元素
STL实践指南  作者 Jeff Bogan
[Boost系列] Boost学习
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服