美文网首页程序员C++2.0
C++11 新特性之 lambda

C++11 新特性之 lambda

作者: Python编程导师 | 来源:发表于2019-02-15 14:14 被阅读16次

这是C++11新特性介绍的第三部分,涉及到C++11这次更新中较为重要的lambda表达式。

不想看toy code的读者可以直接拉到文章最后看这部分的总结。

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;

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

返回类型

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

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

否则,编译器假定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关键字。

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

注:另外本人从事在线教育多年,将自己的资料整合建了一个QQ群,对于有兴趣一起交流学习c/c++的初学者可以加群:941636044,里面有大神会给予解答,也会有许多的资源可以供大家学习分享,欢迎大家前来一起学习进步!

相关文章

  • Lambda函数

    lambda函数定义 lambda函数是C++11中的新特性,名称来自于lambda calculus(λ演算)。...

  • c++11 新特性

    c++11的新特性 1.1 lambda表达式 lambda表达式讲解 例子1: 例子2: C++11中的Lamb...

  • C++11 新特性之 lambda

    这是C++11新特性介绍的第三部分,涉及到C++11这次更新中较为重要的lambda表达式。 不想看toy cod...

  • C++学习笔记(十七) - Lambda函数

    参考文献:C++11新特性:Lambda函数(匿名函数)匿名函数,C++11里面加入了匿名函数。 1 定义一个基本...

  • C++11新特性--lambda

    匿名函数--lambda函数     匿名函数或者匿名类这种语法在其他语言(如lisp,java中)早有应用。在C...

  • lambda表达式

    lambda表达式是C++11引入的新特性,用于声明一个函数,因为不需要对这个函数指定函数名,故lambda表达式...

  • lambda表达式 - C++11中的语言特性(1)

    匿名函数lambda表达式 Java8中提供了类似的特性。C++在C++11中提供了该特性。使用lambda表达式...

  • C++11中std::move、std::forward、左右值

    C++11中std::move、std::forward、左右值引用、移动构造函数的测试 关于C++11新特性之s...

  • C++ 的lambda

    lambda表达式简称lambda式,是C++11 新添加的特性。它适合表达简短、短期调用的可调用对象。 看eff...

  • 阿里巴巴面试题基础篇 C++11

    ● 请问C++11有哪些新特性? 参考回答: C++11 最常用的新特性如下: auto关键字:编译器可以根据初始...

网友评论

    本文标题:C++11 新特性之 lambda

    本文链接:https://www.haomeiwen.com/subject/robpeqtx.html