matlablambda表达式,C++11新特性:Lambda函数(匿名函
数)
加⼊了⾃⼰的理解,不是简单的翻译
C++11终于知道要在语⾔中加⼊匿名函数了。匿名函数在很多时候可以为编码提供便利,这在下⽂会提到。很多语⾔中的匿名函数,如
C++,都是⽤Lambda表达式实现的。Lambda表达式⼜称为lambda函数。我在下⽂中称之为Lambda函数。
基本的Lambda函数
我们可以这样定义⼀个Lambda函数:
#include
usingnamespacestd;
intmain()
{
auto func = [] () { cout <
func(); // now call the function
}
其中func就是⼀个lambda函数。我们使⽤auto来⾃动获取func的类型,这个⾮常重要。定义好lambda函数之后,就可以当这场函数来使⽤了。
其中 [ ] 表⽰接下来开始定义lambda函数,中括号中间有可能还会填参数,这在后⾯介绍。之后的()填写的是lambda函数的参数列表{}中间就是函数体了。
正常情况下,只要函数体中所有return都是同⼀个类型的话,编译器就会⾃⾏判断函数的返回类型。也可以显⽰地指定lambda函数的返回类型。这个需要⽤到函数返回值后置的功能,⽐如这个例⼦:
[] () ->int{return1; }
所以总的来说lambda函数的形式就是:
[captures] (params) -> ret {Statments;}
Lambda函数的⽤处
假设你设计了⼀个地址簿的类。现在你要提供函数查询这个地址簿,可能根据姓名查询,可能根据地址查询,还有可能两者结合。要是你为这些情况都写个函数,那么你⼀定就跪了。所以你应该提供⼀个接⼝,能⽅便地让⽤户⾃定义⾃⼰的查询⽅式。在这⾥可以使⽤lambda函数来实现这个功能。
#include
#include
classAddressBook
{
public:
// using a template allows us to ignore the differences between functors, function pointers
// and lambda
template
std::vector<:string> findMatchingAddresses (Func func)
{
std::vector<:string> results;
for( auto itr = _addresses.begin(), end = _d(); itr != end; ++itr )
{
// call the function passed into findMatchingAddresses and see if it matches
if( func( *itr ) )
{
results.push_back( *itr );
}
}
returnresults;
}
private:
std::vector<:string> _addresses;
};
从上⾯代码可以看到,findMatchingAddressses函数提供的参数是Func类型,这是⼀个泛型类型。在使⽤过程中应该传⼊⼀个函数,然后分别对地址簿中每⼀个entry执⾏这个函数,如果返回值为真那么表明这个entry符合使⽤者的筛选要求,那么就应该放⼊结果当中。那么这个Func类型的参数如何传⼊呢?
AddressBook global_address_book;
vector findAddressesFromOrgs ()
{
returnglobal_address_book.findMatchingAddresses(
// we're declaring a lambda here; the [] signals the start
[] (conststring& addr) {returnaddr.find(".org") != string::npos; }
);
}
可以看到,我们在调⽤函数的时候直接定义了⼀个lambda函数。参数类型是
conststring& addr
返回值是bool类型。
如果⽤户要使⽤不同的⽅式查询的话,只要定义不同的lambda函数就可以了。
Lambda函数中的变量截取
在上述例⼦中,lambda函数使⽤的都是函数体的参数和它内部的信息,并没有使⽤外部信息。我们设想这样的⼀个场景,我们从键盘读⼊⼀个名字,然后⽤lambda函数定义⼀个匿名函数,在地址簿中查有没有相同名字的⼈。那么这个lambda函数势必就要能使⽤外部block 中的变量,所以我们就得使⽤变量截取功能(Variable Capture)。
// read in the name from a user, which we want to search
string name;
cin>> name;
returnglobal_address_book.findMatchingAddresses(
// notice that the lambda function uses the the variable 'name'
[&] (conststring& addr) {returnname.find( addr ) != string::npos; }
); 从上述代码看出,我们的lambda函数已经能使⽤外部作⽤域中的变量name了。这个lambda函数⼀个最⼤的区别是[]中间加⼊了&符号。这就告诉了编译器,要进⾏变量截取。这样lambda函数体就可以使⽤外部变量。如果不加⼊任何符号,编译器就不会进⾏变量截取。
variable used in lambda下⾯是各种变量截取的选项:
[]不截取任何变量
[&}截取外部作⽤域中所有变量,并作为引⽤在函数体中使⽤
[=]截取外部作⽤域中所有变量,并拷贝⼀份在函数体中使⽤
[=, &foo] 截取外部作⽤域中所有变量,并拷贝⼀份在函数体中使⽤,但是对foo变量使⽤引⽤
[bar] 截取bar变量并且拷贝⼀份在函数体重使⽤,同时不截取其他变量
[this] 截取当前类中的this指针。如果已经使⽤了&或者=就默认添加此选项。
Lambda函数和STL
lambda函数的引⼊为STL的使⽤提供了极⼤的⽅便。⽐如下⾯这个例⼦,当你想便利⼀个vector的时候,原来你得这么写:
vector v;
v.push_back( 1 );
v.push_back( 2 );
//...
for( auto itr = v.begin(), end = v.end(); itr != end; itr++ )
{
cout <
} 现在有了lambda函数你就可以这么写
vector v;
v.push_back( 1 );
v.push_back( 2 );
//...
for_each( v.begin(), v.end(), [] (intval)
{
cout <
} ); ⽽且这么写了之后执⾏效率反⽽提⾼了。因为编译器有可能使⽤”循环展开“来加速执⾏过程(计算机系统结构课程中学的)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论