lambda 表达式

简介: lambda 表达式

1. lambda 表达式的语法

[捕捉列表] (参数列表) mutable ->return_type {函数体}

  • (参数列表) :与函数传参一致。不需要传递参数时,可以连同 () 省略。
  • mutable :传值捕捉时,mutable 可以取消参数的常性,使其在函数体内能被修改。不使用时,可以省略;使用该修饰符时,(参数列表) 不可省略(即使参数列表为空)。
  • ->return_type :函数体的返回值类型,通常可以省略,由编译器自行推导。

C++11 中,最简单的 lambda 表达式为 []{},但它没有任何作用。

1.2 lambda 用于sort的一个场景
struct Goods
{
    string _name;// 名称
    double _price;// 价格
    double _evaluations;// 评价
    Goods(const string& name, double price, double evaluations)
        :_evaluations(evaluations)
        , _price(price)
        , _name(name)
    {}
};
int main()
{
    vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,3 }, { "菠萝", 1.5, 4 } };
    auto price = [](const Goods& g1, const Goods& g2) { return g1._price > g2._price; };
    auto evaluation = [](const Goods& g1, const Goods& g2) { return g1._evaluations > g2._evaluations; };
    
    // 按价格排降序
    sort(v.begin(), v.end(), price);
    // 按评价排降序
    sort(v.begin(), v.end(), evaluation);
    return 0;
}

通过以上场景,可以看出 lambda表达式 实际上是匿名仿函数

2. 值传递捕捉/引用传递捕捉与 mutable

2.1 值传递捕捉 和 mutable
int main()
{
    int x = 10, y = 20;
    // 值传递捕捉 x
    auto fun1 = [x] {
        // ++x; // “x”: 无法在非可变 lambda 中修改通过复制捕获
    };
    
    
    // 使用 mutable 时,(参数列表) 不可省略
    auto fun2 = [x]()mutable {
        // x += (y + 2);// 无法隐式捕获“y”,因为尚未指定默认捕获模式
        x += 2;
        cout << x << endl; 
    };
    fun2();// 函数体内的 x 是一个临时变量,
    cout << x << endl;// 修改函数体内的 x 不会改变 被捕捉的/函数体外的 x
    
    
    // 捕捉列表为 = 时,可以以值传递捕捉的方式,隐式捕捉当前作用域所有可访问的对象
    auto fun3 = [=] {
        return x*2 + y;
    };// 省略 ->return_type 时,编译器会自动推导
    int tmp = fun3();
    cout << tmp << endl;
    
    return 0;
}
2.2 引用传递捕捉
int main()
{
    int x = 10, int y = 20;
    
    // 引用传递捕捉 x
    auto fun1 = [&x] {
        ++x;
        cout << x << endl;
    };
    fun1();
    cout << x << endl;
    
    
    // 捕捉列表为 & 时,可以以引用传递捕捉的方式,隐式捕捉当前作用域所有可访问的对象
    auto fun2 = [&] {
        y++;
        x += y;
    };
    fun2();
    cout << x << endl;
    cout << y << endl;
    
    return 0;
}

PS:

  1. “当前作用域”:指包含该 lambda表达式的作用域。
  2. 语法上,捕捉列表可由多个捕捉对象组成,以逗号分割。
int main()
{
    int x, y;
    // 引用传递捕捉 x,值传递捕捉 y
    auto add_x = [&x, y](int a) mutable {
        cin >> y;
        x = y*2 + a;
    };
    add_x(10);
    
    return 0;
}
  1. 捕捉列表不允许变量重复传递,否则会导致编译出错。
int main()
{
    int x = 1, y = 2;
    // [=, x] {};// 重复捕捉 x // error
    [=, &x] {}; // 引用传递捕捉 x,值传递捕捉当前作用域的其他可访问对象
    
    // [&, &x] {}; // error
    [&, x] {};// 值传递捕捉 x,引用传递捕捉当前作用域的其他可访问对象
    
    return 0;
}
  1. 块作用域外的 lambda表达式 捕捉列表必须为空。
auto func = [] {
    cout << "Hello World!" << endl;
};
int main()
{
    func();
    return 0;
}
  1. lambda表达式 之间不能相互赋值。
int main()
{
    auto f1 = [] { cout << "hello world!" << endl; };
    auto f2 = [] { cout << "hello world!" << endl; };
    // f2 = f1;// error
    
    auto f3(f1);
    
    return 0;
}

3. 函数对象 与 lambda表达式

调用 f1() f2() 的反汇编:

注意看:<lambda_xxxx>::operator()operator() 的方式不是类重载“函数调用运算符”吗?

也就意味着,如果定义了一个 lambda表达式,编译器会自动生成一个类,重载 operator(),且 lambda表达式 的名称是编译器根据特定算法实时生成的、保证不重复。

此处解释了,“为什么 lambda表达式 之间不能相互赋值”。

相关文章
|
2月前
|
存储 JavaScript 前端开发
c++lambda函数与表达式
c++lambda函数与表达式
16 1
|
7月前
|
Python
lambda
lambda 是一个匿名函数,它通常用于简化代码,使代码更简洁、易读。lambda 函数不需要显式地使用 def 关键字进行定义,可以直接在表达式中使用。它的语法如下:
101 6
|
安全 架构师 Java
必须掌握的 Lambda 表达式
必须掌握的 Lambda 表达式
5870 1
必须掌握的 Lambda 表达式
|
10月前
|
算法 编译器
【lambda函数】lambda()函数
【lambda函数】lambda()函数
|
10月前
|
存储 算法 编译器
C++ lambda 表达式
# C++ `lamdba` 表达式 > Lambda表达式是C++11引入的一个新特性,它允许我们在需要函数对象的地方,使用一种更加简洁的方式定义匿名函数。Lambda表达式通常用于`STL`中的算法、回调函数、事件处理程序等场合。 Lambda表达式的基本语法为: ```c++ Copy Code[capture list](parameter list) mutable exception -> return type { function body } ``` ## `lamdba`表达式在什么场合下使用 C++11 lambda表达式可以用来创建匿名函数,也就是没有函数名的
70 0
|
10月前
|
设计模式 Java API
值得使用Lambda的8个场景,别再排斥它了!
前言 可能对不少人来说,Lambda显得陌生又复杂,觉得Lambda会导致代码可读性下降,诟病Lambda语法,甚至排斥。
|
Java
Lambda 表达式Demoo
Lambda 表达式Demoo
104 0
Lambda 表达式Demoo
|
存储 算法 编译器
【C++】lambda 表达式 | 包装器
【C++】lambda 表达式 | 包装器
【C++】lambda 表达式 | 包装器
|
并行计算 Java 编译器
Lambda 表达式
Lambda 表达式
152 0
Lambda 表达式
|
Java 编译器
深入理解 Lambda 表达式
Java 8 的 Lambda 表达式已经不再是“新特性”。 现在很多人工作中会使用 Lambda 表达式。 但是,你是否真正理解 Lambda 表达式的底层原理?
385 0
深入理解 Lambda 表达式