c++11中的匿名函数(lambda表达式)

    最近在学习安卓播放的omx的代码,在allocateNode的时候发现有个函数很奇怪:

status_t LWOmx::allocateNode(
        char const* name,
        sp const& observer,
        sp* omxNode) {
    status_t fnStatus;
    status_t transStatus = toStatusT(mBase->allocateNode(
            name, new TWOmxObserver(observer),
            [&fnStatus, omxNode](Status status, sp const& node) {
                fnStatus = toStatusT(status);
                *omxNode = new LWOmxNode(node); // 这块是啥?
            }));
    return transStatus == NO_ERROR ? fnStatus : transStatus;
}

Return Omx::allocateNode(const hidl_string& name, const sp& observer, allocateNode_cb _hidl_cb) {
    ......
    _hidl_cb(toStatus(OK), new TWOmxNode(instance));
	return Void();
}

[&fnStatus, omxNode](Status status, sp const& node) 这是个什么东东?

                   c++11中的匿名函数(lambda表达式)_第1张图片

本着一颗热爱学习的心,我研究(度)了一下。

原来这个东东就是c++11中的新功能: 匿名函数(lambda表达式)

所以呢?啥叫匿名函数?别着急,继续往下看。

顾名思义: 匿名函数, 就是定义时未直接指定名称的函数.

匿名函数有啥优点呢?

非匿名函数在定义时,就已经创建函数对象和作用域对象;所以,即使未调用,也占用内存空间;

匿名函数,仅在调用时,才临时创建函数对象和作用域链对象;调用完,立即释放,所以匿名函数比非匿名函数更节省内存空间.

 

匿名函数表达式格式如下:

[capture] (parameters) mutable exception attribute -> return_type { body }

必须用方括号括起来的capture列表来开始一个lambda表达式的定义。

如果函数体只有一个return語句,或者返回值类型为void,那么返回值类型声明(capture)可以被省略:

 

lambda函数的使用场景1:

std::vector some_list{ 1, 2, 3, 4, 5 };
int total = 0;
std::for_each(begin(some_list), end(some_list), [&total](int x) {  total += x; });
// 这里[&total](int x) {  total += x; }就是lambda函数。total就表示list中所有元素只和。

 看到这里,估计又有人问,for_each是个啥?

 for_each也是c++11的新功能,大概看一下:

template
Function for_each(InputIterator beg, InputIterator end, Function f) {
  while(beg != end) 
    f(*beg++);
}

 看到这里就比较清晰了,上面对lambda的应用实际就是把some_list中的元素逐个当做参数传给lambda函数,然后把所有元素加起来。

lambda函数的使用场景2:

#include 
#include 
#include 

double eval(std::function f, double x = 2.0)
{
	return f(x);
}

int main()
{
	std::function f0    = [](double x){return 1;};
	auto                          f1    = [](double x){return x;};
	decltype(f0)                  fa[3] = {f0,f1,[](double x){return x*x;}};
	std::vector     fv    = {f0,f1};
	fv.push_back                  ([](double x){return x*x;});

	for(auto &f : fv)
		std::cout << "fv: " << f(2.0) << std::endl;
	for(auto &f : fa)
		std::cout  << "fa: " << f(2.0) << std::endl;
	std::cout  << "eval(f0): " << eval(f0) << std::endl;
	std::cout  << "eval(f1): " << eval(f1) << std::endl;
	std::cout  << "eval([]): " << eval([](double x){return x*x;}) << std::endl;
	return 0;
}

运行结果:

fv: 1
fv: 2
fv: 4
eval(f0): 1
eval(f1): 2
eval([]): 4

     这里其他几个都好理解,我们看看最后一个eval([](double x){return x*x;}) ,这里首先是函数eval,他的第一个参数是一个函数,这个函数的定义在调用eval的地方,也就是[](double x){return x*x;},所以,调用eval([](double x){return x*x;} 就是把eval第二个参数double x赋值给第一个参数(函数f)的形参x,然后对x求平方并返回。

     了解了这些之后,我们再来看omx里面allocateNode函数的意思:

                                     c++11中的匿名函数(lambda表达式)_第2张图片

   阴影部分就是lambda函数的的定义。

_hidl_cb(toStatus(OK), new TWOmxNode(instance));

 这里是对lambda函数的调用,实际就是把toStatus(OK)赋值给上面的Status status,把new TWOmxNode(instance)赋值给sp const& node。然后,后面的操作就是函数体里面的过程。

   emmm……到这里就全部结束了,下班回家~

你可能感兴趣的:(基础知识)