each和transform算法下的使用

以前,在lambda表达式没有进入标准的时候,对容器的遍历等涉及到使用函数指针的情况,一般人会懒得使用std::for_each,或std::transform,也许只是一个短短的几句话,却要单独写个函数,或函数对象,写的代码反而不如自己用for循环来的快。但是,C++11引入了lambda表达式后,一切都变的简单了!

1.lambda表达式

lambda表达式是一个匿名函数,用它可以非常方便的表示一个函数对象,先简单说一下lambda表达式,下面这张图表示了C++11中lambda表达式的写法

Lambda表达式的引入标志,在‘[]’里面可以填入‘=’或‘&’表示该lambda表达式“捕获”(lambda表达式在一定的scope可以访问的数据)的数据时以什么方式捕获的,‘&’表示一引用的方式;‘=’表明以值传递的方式捕获,除非专门指出。

Lambda表达式的参数列表

Mutable 标识(可以没有)

异常标识(可以没有)

返回值,如果没有,可以不写

“函数”体,也就是lambda表达式需要进行的实际操作

下面看看几个lambda表达式的例子

void print(int a){……}上面函数lambda表达式为:[](int a){……}上面这个是无返回值的例子,下面这个是有返回值的例子int add(int a,int b){……}上面函数lambda表达式为:[](int a,int b)->int{……}当需要引入其他变量的时候,如有个类的成员变量需要引用或者函数局部变量这种情况下可以显示声明需要引入的变量如成员变量:double m_result;函数:void foo(int a,double b){……use(m_result);}其lambda表达式可以表示为[m_result](int a,int b){……use(m_result);}如果lambda表达式需要修改m_result的值,可以以引用方式传递进去[&m_result](int a,int b){……m_result = 12.1;……}

如果要传入的参数很多,或者干脆在这个作用域里的所有参数都想用到,可以直接在中括号里使用”=“或”&“

如下例子,g_bb为一个全局变量,fun3的lambda表达式把所有内容以引用方式传入:

double g_bb = 11.2;void foo1(){auto f_add = [&](int a,int b)->int{return a+b;};std::cout<<f_add(1,2);//3std::cout<<std::endl;double aa = 5.0;auto fun = [aa]()->double{return aa+3;};//此时aa不能进行赋值操作如:aa=7;std::cout<<fun();std::cout<<" aa:"<<aa<<std::endl;//8 aa:5auto fun2 = [&aa]()->double{aa = 7.0;return aa+3;};//此时aa以引用方式传入,可以进行赋值操作如:aa=7,同时修改aa的值;std::cout<<fun2();std::cout<<" aa:"<<aa<<std::endl;//10 aa:7auto fun3 = [&]()->double{aa = 8.0;g_bb = 15;return aa+3;};//此时aa可以进行赋值操作如:aa=7;,其他在作用域范围的变量都可以以引用方式调用std::cout<<fun3();std::cout<<" aa:"<<aa<<" g_bb:"<<g_bb<<std::endl;//11 aa:8}输出:38 aa:510 aa:711 aa:8 g_bb:15

一般也是以这种方式来写[&],简单明了。

lambda表达式先说到这后面在讲std::for_each和std::transform时会有更多例子。

2.std::foreach

std::foreach是很经典的算法,但是由于需要用到函数对象,有时候还不如直接for循环方便(暂且不讨论for循环的新表达式写法,目前没多少个编译器支持),例如我有个vector,我要打印出来看看里面有什么内容,经常下意识的就直接成:

std ::vector <double>v ;v . push_back ( 3);v . push_back ( 1. 666);v . push_back ( 4. 5);v . push_back ( 6. 7);for( std ::vector <double>::iterator i =v . begin (); i !=v . end (); ++i ){std ::cout <<*i <<",";}

std :: vector < double >:: iterator是多么的碍眼的。

还好,C++11把auto升了级,上面那个代码会变成

for( autoi =v . begin (); i !=v . end (); ++i )用std::foreach(),上面这个就变成std ::for_each ( v . begin (), v . end (),[ &]( double d ){ std ::cout <<d <<",";});

于是,以后凡是要遍历容器,且代码不太长,,都可以使用std::foreach加lambda表达式方便实现

为了方便下面的演示,编写一个打印容器内容的函数printElement

template<typename Container>void printElement(Container& v){std::cout<<"(";for(auto i = v.begin();i != v.end();++i){std::cout<<*i;if(i != v.end() – 1)std::cout<<",";}std::cout<<")";std::cout<<std::endl;}

可以输出序列的内容,如vector<double>内容为(1,2,3,4,5),输出:(1,2,3,4,5)

3.std::transform

当涉及到两个或三个容器的操作,就需要使用std::transform操作

transform有两个重载版本

template <class InputIterator, class OutputIterator, class UnaryOperation> OutputIterator transform (InputIterator first1, InputIterator last1,OutputIterator result, UnaryOperation op);原理如下图所示:

template <class InputIterator1, class InputIterator2,class OutputIterator, class BinaryOperation>;OutputIterator transform (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, OutputIterator result,BinaryOperation binary_op);原理如下图所示:风景如何,其实并不重要。重要的是,你在我的身边。

each和transform算法下的使用

相关文章:

你感兴趣的文章:

标签云: