lambda表达式是c++11新增的一种匿名函数定义的方式,主要的形式是:
[capture](para)specifies->returntype{body}
capture
capture是捕获的外部变量列表,使用逗号分隔,外部变量可以通过传值或者引用。
lambda表达式的body和这些外部变量组成闭包,外部变量则成为了这个闭包的成员变量。
比如下面这个lambda表达式经过编译器展开之后就会变成如下形式:
int sum = 0;
std::vector<int> arr = {1,2,3};
std::for_each(begin(arr), end(arr), [&sum](int x){sum += x});
// 编译之后
struct lambda
{
public:
lambda(int* pSum)
{
m_sum = pSum;
}
void operator()(int x) const
{
*m_sum += x;
}
private:
int* sum;
};
上面我们说到了lamba表达式可以传递不同的capture,以下是一些例子:
auto tmp = [](int x) {return x;}; /*传空表示只能访问全局的变量或作用域内的静态变量*/
auto tmp1 = [value](int x) {int a = value; return a;}; /*传值表示能以读的形式访问value*/
auto tmp2 = [&value](int x) {value++; return value}; /*引用的方式传递value*/
auto tmp3 = [this](int x) {return *this;}; /*传递this指针*/
auto tmp4 = [=]{return x;}; /*没有参数的话可以省略括号,以传值的方式传递所有的外部变量*/
auto tmp5 = [&]{return x;}; /*没有参数的话可以省略括号,以传引用的方式传递所有的外部变量*/
需要注意的是传值的话如果需要能够修改外部变量的值的话,需要加上mutable修饰。
比如:
auto tmp1 = [value](int x) mutable {value++; return value;};
另外一个注意点是使用this指针时需要在类的非静态成员函数中使用,这样才能访问成员函数和变量。
针对caputure,在c++14中还增加了广义捕获的新特性,简单的说就是外部变量可以在被捕获时初始化参数:
auto a1 = [a = 1, b = 2](){return a + b;}
auto res = a1(); // 3
para
表示参数列表,当列表为空的时候可以直接省略括号。
关于参数这部分比较简单,lambda表达式的参数和一般的c++函数的参数的区别有以下几点:
- 不允许使用参数初始化:int fun(int a = 1, int b = 2);
- 不允许省略参数:int fun(int, int);
- 不允许可变长参数:int fun(int count, …);
与此同时,在c++14中,也增加了一些特性:
可以使用auto类型传参:
int tmp = [](auto a, auto b){ return a + b; };
struct lambda {
template<typename T, typename U>
auto operator()(T a, U b) const { return a + b; }
};
支持可变参数:
int func(int n1, int n2,int flag) {
return (flag ? n1 : n2);
}
auto tmp = [](auto&&... params){
return (foo(std::forward<decltype(params)>(params)...));
};
int res = tmp(1, 2, false);
specifies
表示一些说明符,入matuable等
return_type表示返回值类型,一遍可以省略,具体可以参考上面的一些例子。
返回值可以推导出来,所以一般不需要特别指定。
我们一般使用lambda表达式会在一些异步 *** 作中填入执行的逻辑时使用。
将它传递给一个定义好的函数对象:
// 使用对象保存
int Value = 0;
auto a = [](int x){Value = x;};
std::function<float(int, float)> func = [](int x, float y) {return x + y;};
a(1); // 1
func(1, 1.1) // 2.1
// 使用函数指针保存
int(*fun1)(int, int) = [](int x, int y) {return x + y;};
int res = func1(1, 2);
悬挂引用
std::function<int()> a
{
int Value = 0;
a = [&Value] {return Value; };
}
a();
上面的表达式中Value是局部变量,如果在一个异步的调用中,函数调用的时候这个值可能早已释放,再次访问时会造成内存越界。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)