C11中的新特性----lambda表达式

lambda表达式

lambda来源于函数式编程的概念,是现代编程语言的一个特点。
lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量

lambda表达式的基本功能和语法形式

[cature] (params)opt->ret{body;};
//capture是捕获列表;params是参数表;opt是函数选项;ret是返回值类型;body是函数体。
//lambda表达式可以通过捕获列表捕获一定范围内地变量。
  1. **[ ];**不捕获任何变量。
  2. **[ & ];**捕获外部作用域中的所有变量,并作为引用在函数体中使用(按引用捕获)。
  3. **[ = ];**捕获外部作用域中的所有变量,并作为副本在函数体中使用(按值捕获),捕获的内容全部都是只读的,本身的值无法改变。
  4. **[ = , &foo ];**按值捕获外部作用域中的所有变量,并作为引用捕获foo变量。
  5. **[ bar ];**按值捕获bar变量,同时不捕获其他变量。
  6. **[ this ];**捕获当前类中的this指针,让lambda表达式拥有和其他类成员函数同样的访问权限。如果已经使用了&或=,就默认添加此选项。捕获this的目的是可以在lamda中使用当前类的成员函数和成员变量。

注意:全局变量(全局域)不存在捕获概念,捕获只是针对于局部变量(函数域,类域)

lambda表达式的优点

  1. 声明式编程风格:就地匿名定义目标函数或者函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式去写程序,有高的可读性和维护性
  2. 简洁:不需要额外再写一个函数或者函数对象,避免了代码膨胀和功能分散,让开发者更加集中精力工作时,也获得了更高的生产率。
  3. 在需要的时间和地点实现功能闭包,使程序更加灵活。

案例说明


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)
    {
        //error,没有捕获外部变量
        auto x1 = []()->int
        {
           // return a;
        };
        //捕获外部作用域中所有变量,按值捕获(包括全局变量和this指针)
        auto x2 = [=]()->int
        {
            int x = value;
            return x + a + g_max;
        };
        //捕获外部作用域中所有变量,按引用捕获(包括全局变量和this指针)
        auto x3 = [&]()->int
        {
            g_max = 100;
            value += 10;
            return g_max + value;
        };
        //只是捕获this指针
        auto x4 = [this](int c)->int
        {
            value += 100;
            return value + c;
        };
        //error,只是捕获this指针,不捕获a,b
        auto x5 = [this]()->void
        {
           // value = a + b;
        };
        //只是捕获this指针,a,b
        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++;//error,=改为&即可
    };
    auto f4 = [=]()mutable->int
    {
        return a++;//OK
    };
    auto f5(f1);//OK
    f1 = f2;//error,lambda表达式之间不能赋值
    ptr p1 = f1;//OK
    auto f4 = [=](int x)->void
    {
        cout << "hello" << endl;
    };
    ptr p2 = f4;//error

}

总结

被mutable修饰的lambda表达式就算没有参数也要写明参数列表
lambda表达式可以说是就地定义仿函数闭包的“语法糖”。他的捕获列表捕获住的任何外部变量,最终均会变为闭包类型的成员变量。而一个使用了成员变量的类的operator(),如果能直接被转换为普通的函数指针,那么lambda表达式本身的this指针就丢失了。而没有捕获任何外部变量的lamba表达式则不存在这个问题。
这里也可以很自然地解释为什么按值捕获无法修改捕获的外部变量。在C++中,lambda表达式的operator()默认是const的方法。一个const成员函数是无法修改成员变量的值的。而mutable的作用,就在于取消operator()的const。
没有捕获变量的lambda表达式可以直接转换为函数指针,而有捕获变量的lambda表达式则不能转换为函数指针。

案例3

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值