浅析C++11新特性的Lambda表达式

 更新时间:2016年08月01日 17:59:14   投稿:daisy  
C++11 新增了很多特性,lambda 表达式是其中之一,本文涉及到C++11这次更新中较为重要的lambda表达式。有需要的朋友们可以参考学习。

lambda简介

熟悉Python的程序员应该对lambda不陌生。简单来说,lambda就是一个匿名的可调用代码块。在C++11新标准中,lambda具有如下格式:

[capture list] (parameter list) -> return type { function body }

可以看到,他有四个组成部分:

    1.capture list: 捕获列表

    2.parameter list: 参数列表

    3.return type: 返回类型

    4.function body: 执行代码

其中,参数列表和返回类型可以忽略。

下面,具体看几个简单的例子:

auto f1 = [] { return 1; };
auto f2 = [] () { return 2; };
cout<<f1()<<'\t'<<f2()<<endl;

捕获列表

lambda中的捕获列表既可以捕获值,也可以捕获引用。

捕获值:

int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17};
int border = 8;
auto f3 = [border](const int &i){ if(i > border) cout<<i<<'\t'; };
for_each(begin(test_data), end(test_data), f3);
cout<<endl;

捕获引用:

auto f4 = [&border](const int &i){ if(i > border) cout<<i<<'\t'; };
border = 6;
for_each(begin(test_data), end(test_data), f4);
cout<<endl;

通过输出可以看出,lambda中起作用的border是修改后的6,证实了捕获的确是是引用。

需要注意的是,在捕获引用时,需要保证当lambda被调用时,此引用仍然有效。

捕获列表还可以采用隐式捕获的方式,即让编译器通过lambda的执行代码来判断需要捕获哪些局部变量。

隐式捕获可以捕获值、引用或者两者混合:

char space = ' ';
auto f5 = [=](const int &i){ if(i > border) cout<<i<<'\t'; };
auto f6 = [&](const int &i){ if(i > border) cout<<i<<'\t'; };
auto f7 = [&, space](const int &i){ if(i > border) cout<<i<<space; };
border = 0;
for_each(begin(test_data), end(test_data), f5);
cout<<endl;
for_each(begin(test_data), end(test_data), f6);
cout<<endl;
for_each(begin(test_data), end(test_data), f7);
cout<<endl;

这里的f7使用的混合形式,可以读作“除了space捕获值之外,其他变量均捕获引用”。

可变lambda

lambda需要在其中修改被值捕获的变量的值时,需要给lambda加上mutable关键字。否则会有编译错误。

auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<<i<<space; space='\t';} };
for_each(begin(test_data), end(test_data), f8);
cout<<endl;
cout<<1<<space<<2<<endl;

从输出中可以看出,spacelambda f8中的值,在第一次调用之后,就被变成了制表符Tab;但是在lambda之外,space仍然是空格。

返回类型

lambda的返回类型采用尾置返回类型的方式。一般的:

    1.lambda如果只包含return语句,则编译器可以推断其返回类型,此时可以不显示指定返回类型;

    2.否则,编译器假定lambda返回void,而返回void的函数不可以反悔任何具体值,这在大多数情况下是个矛盾,因此需要显示指定返回类型。

但是,经过实际测试,目前的g++编译器更聪明了:对于第2点,目前只要编译器可以从lambda函数体中推断出函数的返回类型,就不需要显式指定返回类型,例如:

auto f9 = [](const int i){if(i % 3) return i * 3; else return i;};
transform(begin(test_data), end(test_data), begin(test_data), f9);
border = 0;
for_each(begin(test_data), end(test_data), f6);
cout<<endl;

lambda代码块中有多个return语句,并且还有if/else语句,但是编译器可以根据return语句推断出,其返回值应该是一个int类型,所以可以省略尾置返回类型。

但是,像下面这种形式,由于编译器在推断返回类型时发现了不一致,所以必须显式的指定返回类型:

auto f10 = [](const int i) -> double
{if(i % 5) return i * 5.0; else return i;};
transform(begin(test_data), end(test_data), begin(test_data), f10);
for_each(begin(test_data), end(test_data), f6);
cout<<endl;

总结

    1.lambda表达式形式: [capture list] (parameter list) -> return type { function body },其中parameter list和return type可以省略。

    2.捕获列表可以捕获值[val],也可以捕获引用[&ref]。

    3.捕获列表还可以隐式捕获局部变量,同样有捕获值[=]和捕获引用[&]两种方式,初次之外还可以混合捕获[&, val]或者[=, &ref]

    4.当lambda需要修改捕获的值时,需要加上mutable关键字。

    4.当lambda无法自动推断出返回值类型时,需要通过尾置返回类型的方式显示指定。

以上就是C++11新特性之Lambda表达式的全部内容,希望本文对大家学习C++有所帮助。

相关文章

  • c++ 前自增/后自增操作符效率分析

    c++ 前自增/后自增操作符效率分析

    这篇文章主要介绍了c++ 前自增/后自增操作符效率分析,帮助大家更好的理解和学习c++,感兴趣的朋友可以了解下
    2021-01-01
  • 哈夫曼的c语言实现代码

    哈夫曼的c语言实现代码

    着先通过 HuffmanTree() 函数构造哈夫曼树,然后在主函数 main()中自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在父结点左侧,则置码为 0,若在右侧,则置码为 1。最后输出生成的编码
    2013-07-07
  • 直观理解C语言中指向一位数组与二维数组的指针

    直观理解C语言中指向一位数组与二维数组的指针

    这篇文章主要介绍了直观理解C语言中指向一位数组与二维数组的指针,数组指针是C语言入门学习过程中的重点和难点,需要的朋友可以参考下
    2016-05-05
  • C语言数据结构进阶之栈和队列的实现

    C语言数据结构进阶之栈和队列的实现

    栈和队列,严格意义上来说,也属于线性表,因为它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,因此将其单独作为一章,做重点讲解
    2021-11-11
  • C语言数据结构与算法之排序总结(一)

    C语言数据结构与算法之排序总结(一)

    这篇文章主要介绍了数据结构与算法中的插入类和交换类的各种排序,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2021-12-12
  • C++实现LeetCode(51.N皇后问题)

    C++实现LeetCode(51.N皇后问题)

    这篇文章主要介绍了C++实现LeetCode(51.N皇后问题),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • VS2019开发简单的C/C++动态链接库并进行调用的实现

    VS2019开发简单的C/C++动态链接库并进行调用的实现

    这篇文章主要介绍了VS2019开发简单的C/C++动态链接库并进行调用的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • C++实现简易通讯录

    C++实现简易通讯录

    这篇文章主要为大家详细介绍了C++实现简易通讯录,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • C语言单值二叉树真题讲解

    C语言单值二叉树真题讲解

    单值二叉树你可能之前没见过,如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树,让我们通过一个真题来深刻了解它吧
    2022-04-04
  • c语言中if 语句的作用范围示例代码

    c语言中if 语句的作用范围示例代码

    if语句的作用范围只有紧跟if的第一条表达式,下面的示例将告诉你,感兴趣的朋友可以了解下
    2013-09-09

最新评论