您的位置:首页 > 编程语言 > C语言/C++

C++ lambda表达式

2017-04-08 21:55 288 查看
C++11及之后的lambda表达式是一个强大的工具,它可以表示一个可调用的代码单元。可以理解为一个未命名的内联函数。一个lambda表达式具有如下形式:

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


我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体。

auto f = [] { return 42; };
cout << f() << endl; // print 42


lambda表达式常常和for_each以及迭代器一起使用。如下,需要对vector中的每一个值求平方:

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
vector<int> test = {3,2,5};
for(auto v: test) cout << v << " ";
cout << endl;
for_each(test.begin(), test.end(), [] (int& a) { a *= a; });
for(auto v: test) cout << v << " ";
cout << endl;
return 0;
}


这是输出的结果:



当然了,除了这个方法,还可以用函数指针来解决这个问题:

#include <iostream>
using namespace std;

typedef int (*pf)(int);
template <class T>
void square(vector<T>& vec, pf func) {
for (auto &v: vec) v *= v; // need to use reference
}

int main(int argc, const char * argv[]) {
vector<int> test = {3,2,5};

for(auto v: test) cout << v << " ";
cout << endl;

square(test, squareTest);
//for_each(test.begin(), test.end(), [](int& a){ a *= a; });

for(auto v: test) cout << v << " ";
cout << endl;
return 0;
}


最后的结果是一样的。

这个在Python中直接使用map就能达到相同的效果:

def squareTest(a):
return a**2

test = [3,2,5]
print(test)
print(map(squareTest, test))
# print(map(lambda a : a**2 , test)) # can use lambda as well


map中第一个参数表示需要实施的函数,而第二个参数表示函数实施的对象。而对于lambda,和C++比较相似,但语法不一样。

下面对lambda中的捕获列表做一些说明,捕获列表可以是值传递,即传入一个拷贝,或是引用传递,即传递的是一个引用,对引用进行的操作会直接影响到被引用的对象的值。

下面举个例子说明:

int main(int argc, const char * argv[]) {
size_t v1 = 42;
auto f = [v1] { return v1; };
v1 = 2;
auto j = f();
cout << j << endl; // j = 42

size_t v2 = 42;
auto f1 = [&v2] { return v2; };
v2 = 2;
auto k = f1();
cout << k << endl; // k = 2
return 0;
}


第一个是值传入,最后输出的是对之前v1的拷贝的值,v1的改变并不会对最后j的值造成影响,所以最后j的值还是42。而第二个例子中传入的引用,这时此引用指向被引用的对象,即v2,于是它们幸福地绑定在一起了,后面对v2进行了变化,那么引用也会跟随,即最后k的值也变成了2。

其实也可以对传入的捕获值进行变化,对于值传递,需要加一个关键词mutable。而对于引用传递,可不可以变化,要看传入值是不是const类型,如果是,则不能;如果不是,则可以。那么看下面的例子:

int main(int argc, const char * argv[]) {
size_t v1 = 42;
auto f = [v1] () mutable { return ++v1; };
v1 = 2;
auto j = f();
cout << j << endl; // j = 43
cout << v1 << endl; // v1 = 2

size_t v2 = 42;
auto f1 = [&v2] { return ++v2; };
v2 = 2;
auto k = f1();
cout << k << endl; // k = 3
cout << v2 << endl;// v2 = 3

return 0;
}


这里分别输出了调用lambda表达式的值和被捕获的值。对于值传递,改变了v1的拷贝的值,于是j等于了43,而v1还是42;对于引用传递,由于绑定的原因,对引用的改变,那么被引用的变量的值也会变,所以最后k和v2的值都变成了3。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++