源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

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

  • 时间:2021-01-31 04:53 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:浅析C++11新特性的Lambda表达式
[b]lambda简介[/b] 熟悉Python的程序员应该对[b]lambda[/b]不陌生。简单来说,[b]lambda[/b]就是一个匿名的可调用代码块。在C++11新标准中,[b]lambda[/b]具有如下格式:
[capture list] (parameter list) -> return type { function body }
可以看到,他有四个组成部分:    [b]1.capture list:[/b] 捕获列表    [b]2.parameter list: [/b]参数列表    [b]3.return type: [/b]返回类型    [b]4.function body:[/b] 执行代码 其中,参数列表和返回类型可以忽略。 下面,具体看几个简单的例子:
auto f1 = [] { return 1; };
auto f2 = [] () { return 2; };
cout<<f1()<<'\t'<<f2()<<endl;
[b]捕获列表[/b] [b]lambda[/b]中的捕获列表既可以捕获值,也可以捕获引用。 [b]捕获值:[/b]
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;
[b]捕获引用:[/b]
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;
通过输出可以看出,[b]lambda[/b]中起作用的[b]border[/b]是修改后的6,证实了捕获的确是是引用。 [b]需要注意的是[/b],在捕获引用时,需要保证当[b]lambda[/b]被调用时,此引用仍然有效。 捕获列表还可以采用隐式捕获的方式,即让编译器通过[b]lambda[/b]的执行代码来判断需要捕获哪些局部变量。 隐式捕获可以捕获值、引用或者两者混合:
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使用的混合形式,可以读作“[b]除了space捕获值之外,其他变量均捕获引用[/b]”。 [b]可变lambda[/b] 当[b]lambda[/b]需要在其中修改被值捕获的变量的值时,需要给[b]lambda[/b]加上[b]mutable[/b]关键字。否则会有编译错误。
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;
从输出中可以看出,[b]space[/b]在[b]lambda f8[/b]中的值,在第一次调用之后,就被变成了制表符Tab;但是在[b]lambda[/b]之外,[b]space[/b]仍然是空格。 [b]返回类型[/b] [b]lambda[/b]的返回类型采用尾置返回类型的方式。一般的:     1.[b]lambda[/b]如果只包含[b]return[/b]语句,则编译器可以推断其返回类型,此时可以不显示指定返回类型;     2.否则,编译器假定[b]lambda[/b]返回[b]void[/b],而返回[b]void[/b]的函数不可以反悔任何具体值,这在大多数情况下是个矛盾,因此需要显示指定返回类型。 但是,经过实际测试,目前的g++编译器更聪明了:对于第2点,目前只要编译器可以从[b]lambda[/b]函数体中推断出函数的返回类型,就不需要显式指定返回类型,例如:
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;
[b]lambda[/b]代码块中有多个[b]return[/b]语句,并且还有[b]if/else[/b]语句,但是编译器可以根据[b]return[/b]语句推断出,其返回值应该是一个[b]int[/b]类型,所以可以省略尾置返回类型。 但是,像下面这种形式,由于编译器在推断返回类型时发现了不一致,所以必须显式的指定返回类型:
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;
[b]总结[/b]     1.[b]lambda[/b]表达式形式: [code][capture list] (parameter list) -> return type { function body },[/code]其中[b]parameter list和return type[/b]可以省略。     2.捕获列表可以捕获值[code][val],[/code]也可以捕获引用[code][&ref]。[/code]     3.捕获列表还可以隐式捕获局部变量,同样有捕获值[=]和捕获引用[&]两种方式,初次之外还可以混合捕获[code][&, val][/code]或者[code][=, &ref][/code]。     4.当[b]lambda[/b]需要修改捕获的值时,需要加上[b]mutable[/b]关键字。     4.当[b]lambda[/b]无法自动推断出返回值类型时,需要通过尾置返回类型的方式显示指定。 以上就是C++11新特性之Lambda表达式的全部内容,希望本文对大家学习C++有所帮助。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部