lamda表达式和尾置返回类型
基本
基本形式如下:
[capture]:叫做捕获说明符,表示一个
mutable: mutable修饰符。默认情况下,lamda函数总是一个const函数,mutable可以取消其常量性,在使用该修饰符时,参数列表不能省略(即使参数为空)。
{body}: 函数体,与普通函数的函数体一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。
我们可以这样输出"hello,world"
auto func = [] () { cout <<
"hello,world"; };
func();
// now call the function
变量捕获与
string name;
cin >> name;
[&](){cout << name;}();
lambda函数能够捕获
- [] 不截取任何变量
- [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
- [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
- [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
- [bar] 截取bar变量并且拷贝一份在函数体中使用,同时不截取其他变量
- [x, &y] x按值传递,y按引用传递
- [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。
看到这,不禁要问,这魔法般的变量捕获是怎么实现的呢?原来,
最后,lambda函数的类型是什么呢,答案是std:function。
////////////////////////////////////////////////////////////////////////////////////////////////
为什么需要
匿名函数是许多编程语言都支持的概念,有函数体,没有函数名。
#include <algorithm>
#include <cmath>
void abssort(float* x, unsigned N) {
std::sort(x, x + N,
// Lambda expression begins
[](float a, float b) {
return std::abs(a) < std::abs(b);
});
}
你可能会问,使用函数对象不是也可以吗?是的,函数对象当然没问题,自己写的回调函数,你可以传个函数指针也没有问题。他们有优点也有缺点。函数对象能维护状态,但语法开销大,而函数指针语法开销小,却没法保存范围内的状态。如果你觉得鱼和熊掌不可兼得,那你可错了。
2.尾置返回类型
有时候,当希望编写一个函数来接收某个序列容器中返回的一个元素的应用时候,你可能就不太能够想明白应该如何写出这个函数的返回值类型了:
template <typename T>
return_type &getItem(T begin, T end) {
return *begin; // 返回序列中一个元素的引用
}
这里的 return_type
应该怎么写呢?事实上,我们可能会想到使用 decltype()
来获得这个类型,但是,编译器在读到这个函数定义的时候,begin 甚至还没有出现,这时候我们似乎没有任何办法直接在返回类型的时候写下这个返回类型。
C++11 提供了一种新的书写返回值的方式,那就是将返回类型尾置。尾置的返回类型允许我们在参数列表之后申明返回的类型,我们的代码可以写成:
template <typename T>
auto &getItem(T begin, T end) -> decltype(*begin) {
return *begin; // 返回序列中一个元素的引用
}
其中,我们使用 decltype 告知了编译器返回类型与参数表中的返回类型相同,而 decltype 会自动推断为元素类型的引用,完成了我们的需求。