C++ lambda 表达式

来源:互联网 发布:箪食壶浆以迎将军乎 编辑:程序博客网 时间:2024/06/07 12:55

1.    我们可以传递任何种callable object给算法,一个object或者expression 称为callable 是因为我们可以应用call operator。

我们说e是一个callable expression,那么我们可以写这样的代码:

<span style="font-size:18px;"><span style="white-space:pre"></span>e(arg);</span>

arg是用逗号隔开的argument list。

2.    callable:function,function pointer,重载了function call operator的class,以及lambda 表达式。

3.    lambda表达式可以被认为是一种unnamed inline function。

4.    lambda表达式的形式为:

<span style="font-size:18px;"><span style="white-space:pre"></span>[capture list](parameter list)->return type{function body}</span>

5.    lambda没有default argument,因此call a lambda 总是传递和parameter数量相同的argument。

6.    lambda能够使用local variables只有当它specified它将要使用的variables才行。lambda通过将这些variables包括在他的capture list来specified这些variables。

7.    当我们定义一个lambda,编译器生成一个新的未命名的class type corresponds to that lambda。当我们传递一个lambda给一个function的时候,我们同时define一个new type以及一个这个type的object。

8.    当我们capture by value的时候,要确保variables能够被copy。同时,value of a capture variable 被copied当lambda被创造的时候,而不是被called的时候。

9.    当我们capture by reference的时候,要确保referenced的object当lambda执行的时候还存在。

10.  当我们implicit capture variables的时候,我们使用[&],[=]来告诉编译器我们到底是capture by reference还是capture by value。同时,当我们同时使用implicit capture 和explicit capture的时候,我们必须使capture list 的第一个是&或者=,同时explicit capture要和implicit capture的类型相反。

11.  by default,lambda不会改变那些capture by value 的variable 的值,当我们想要改变的时候,我们这样:

<span style="font-size:18px;"><span style="white-space:pre"></span>auto f=[v]mutable{return v++;}</span>

12.   Bydefault,如果一个lambda的function body 包括除了return之外的其他语句,lambda都被认为return void。

如:

<span style="font-size:18px;"><span style="white-space:pre"></span>transform(vi.begin(),vi.end(),vi.begin(),[](int i){if(i<0) return –I;   else return I;}</span>

这导致error,因为lambda return a void type 但是我们返回了一个值。

       当我们想要定义一个返回值的时候,我们可以这样做:

<span style="font-size:18px;"><span style="white-space:pre"></span>transform(vi.begin(),vi.end(),vi.begin(),[](int i)->int              { if(i<0)       return –I;   else return I;}</span>

13.  我们可以很容易将capture list 为空的lambda改为一个函数传递给算法,但是对于那些capture local variables 的lambda,则没有这么简单,因为算法通常用 unary predicate或者binary predicate。

14.  解决上面的问题,当我们需要将local variable传递到函数中,又希望可以将此函数传递给算法,我们可以使用bind function,如下:

<span style="font-size:18px;"><span style="white-space:pre"></span>for_each(word.begin(),word.end(),                     bind(print,ref(os),_1,’‘);</span>

     在这里,newCallable就是一个callable object,arg_list是逗号隔开的argument list,correspond to parameter of callable。

     在arg_list里会有一些_n的项,这些argument是placeholder,代表了newCallable中的parameter,_1代表newCallable的第一个parameter,_2代表第二个。

     代码例子:

<span style="font-size:18px;"><span style="white-space:pre"></span>auto wc=find_if(word.begin(),word.end(), bind(check_size,_1,sz));</span>

     注:bind定义在functional头文件里。

15.  _n定义在名叫placeholder的namespace里,placeholder又定义在std的namespace里,

<span style="font-size:18px;"><span style="white-space:pre"></span>using::std::placeholder::_1;</span>

       我们也可以这样简化              

<span style="font-size:18px;"> <span style="white-space:pre"></span>using namespace std::placeholder</span>

16.  bind函数可以帮助我们对参数重排序。

<span style="font-size:18px;"><span style="white-space:pre"></span>sort(word.begin(),word.end(),bind(isShorter,_2,_1);</span>

       改变了参数顺序后,实际上使得排序方向正好相反。

17.  有时候,我们需要bind函数去binding reference parameter,通常那些不是placeholder的argument都是被copy到bind函数return的callable object里的。如果要binding reference parameter,可以这样做。

<span style="font-size:18px;"><span style="white-space:pre"></span>for_each(word.begin(),word.end(),                     bind(print,ref(os),_1,’‘);</span>

ref()函数返回一个包括了给定的reference的object,而且这个object是copyable的。我们还可以用cref()函数生成一个包括了reference to const的类。

 

     

0 0
原创粉丝点击