本文是C++11新特性介绍的第三部分,涉及到C++11这次更新中较为重要的lambda表达式。
lambda 简介
熟悉Python的程序员应该对lambda不陌生。简单来说,lambda就是一个匿名的可调用代码块。在C++11新标准中,lambda具有如下格式:
可以看到,他有四个组成部分:
1.capture list:捕获列表
2.parameter list:参数列表
3.return type:返回类型
4.function body:执行代码
其中,参数列表和返回类型可以忽略。下面,具体看几个简单的例子:
捕获列表
lambda中的捕获列表既可以捕获值,也可以捕获引用。
捕获值:
捕获引用:
通过输出可以看出,lambda中起作用的border是修改后的6,证实了捕获的确是是引用。需要注意的是,在捕获引用时,需要保证当lambda被调用时,此引用仍然有效。捕获列表还可以采用隐式捕获的方式,即让编译器通过lambda的执行代码来判断需要捕获哪些局部变量。
隐式捕获可以捕获值、引用或者两者混合:
这里的f7使用的混合形式,可以读作“除了space捕获值之外,其他变量均捕获引用”。
可变 lambda
当lambda需要在其中修改被值捕获的变量的值时,需要给lambda加上mutable关键字。否则会有编译错误。
从输出中可以看出,space在lambda f8中的值,在第一次调用之后,就被变成了制表符Tab;但是在lambda之外,space仍然是空格。
返回类型
lambda的返回类型采用尾置返回类型的方式。一般的:
1.lambda如果只包含return语句,则编译器可以推断其返回类型,此时可以不显示指定返回类型;
2.否则,编译器假定lambda返回void,而返回void的函数不可以反悔任何具体值,这在大多数情况下是个矛盾,因此需要显示指定返回类型。
但是,经过实际测试,目前的g++编译器更聪明了:对于第2点,目前只要编译器可以从lambda函数体中推断出函数的返回类型,就不需要显式指定返回类型,例如:
总结
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无法自动推断出返回值类型时,需要通过尾置返回类型的方式显示指定。