lambda表达式
lambda来源于函数式编程的概念,是现代编程语言的一个特点。 lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量
lambda表达式的基本功能和语法形式
[cature] (params)opt->ret{body;};
- **[ ];**不捕获任何变量。
- **[ & ];**捕获外部作用域中的所有变量,并作为引用在函数体中使用(按引用捕获)。
- **[ = ];**捕获外部作用域中的所有变量,并作为副本在函数体中使用(按引用值捕获)。
- **[ = , &foo ];**按值捕获外部作用域中的所有变量,并作为引用捕获foo变量。
- **[ bar ];**按值捕获bar变量,同时不捕获其他变量。
- **[ this ];**捕获当前类中的this指针,让lambda表达式拥有和其他类成员函数同样的访问权限。如果已经使用了&或=,就默认添加此选项。捕获this的目的是可以在lamda中使用当前类的成员函数和成员变量。
lambda表达式的优点
- 声明式编程风格:就地匿名定义目标函数或者函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序,有高的可读性和维护性
- 简洁:不需要额外再写一个函数或者函数对象,避免了代码膨胀和功能分散,让开发者更加集中精力工作时,也获得了更高的生产率。
- 在需要的时间和地点实现功能闭包,使程序更加灵活。
案例说明
int g_max = 10;
class Object
{
private:
int value;
public:
Object(int x = 0) :value(x)
{
cout << "Create Object" << this << endl;
}
void func(int a, int b)
{
auto x1 = []()->int
{
};
auto x2 = [=]()->int
{
int x = value;
return x + a + g_max;
};
auto x3 = [&]()->int
{
g_max = 100;
value += 10;
return g_max + value;
};
auto x4 = [this](int c)->int
{
value += 100;
return value + c;
};
auto x5 = [this]()->void
{
};
auto x6 = [this, a, b]()->void
{
value = a + b;
};
}
};
总结
默认状态下lambda表达式无法修改通过复制方式捕获的外部变量。如果希望修改这些变量的话,我们需要使用引用方式进行捕获。
案例2
typedef void (*ptr)(int);
int main()
{
int a = 10, b = 20;
auto f1 = [](int a)->void
{
cout << a << endl;
};
auto f2 = [](int x)->void
{
cout << x + 10 << endl;
};
auto f3 = [=]()->int
{
return a++;
};
auto f4 = [=]()mutable->int
{
return a++;
};
auto f5(f1);
f1 = f2;
ptr p1 = f1;
auto f4 = [=](int x)->void
{
cout << "hello" << endl;
};
ptr p2 = f4;
}
总结
被mutable修饰的lambda表达式就算没有参数也要写明参数列表 lambda表达式可以说是就地定义仿函数闭包的“语法糖”。他的捕获列表捕获住的任何外部变量,最终均会变为闭包类型的成员变量。而一个使用了成员变量的类的operator(),如果能直接被转换为普通的函数指针,那么lambda表达式本身的this指针就丢失了。而没有捕获任何外部变量的lamba表达式则不存在这个问题。 这里也可以很自然地解释为什么按值捕获无法修改捕获的外部变量。在C++中,lambda表达式的operator()默认是const的方法。一个const成员函数是无法修改成员变量的值的。而mutable的作用,就在于取消operator()的const。 没有捕获变量的lambda表达式可以直接转换为函数指针,而有捕获变量的lambda表达式则不能转换为函数指针。
案例3
|