c++11--lambda表达式

发布时间:2024年01月06日

1.概述
lambda表达式实际上是一种就地定义和使用的匿名的可调用类型。类似一种语法糖的存在。

2.lambda形式

[capture] (parameters) mutable -> return-type{ statement };

2.1.capture
捕获列表的形式
a. [var],以值传递方式捕获上一层作用域的自动变量var
b. [=],以值传递方式捕获上一层作用域的全体自动变量(成员函数使用时包括this)。
c. [&var],以引用方式捕获上一层作用域的自动变量var
d. [&],以引用方式捕获上一层作用域的全体自动变量(成员函数使用时包括this)。
e. [this],以值传递方式捕获上一层作用域的自动变量this(必须位于成员函数内)。

可以对上述形式进行组合,如[=, &a, &b],表示以引用方式捕获上一层作用域的自动变量a,b。以值传递方式捕获上一层作用域的其余自动变量。

注意点:
a. 何为自动变量
{}作用域内的局部变量。

int c = 1;
static d = 1;
int fun(int a)
{
	int b;
	return a+b;
}

上述a,b位于fun作用域内是自动变量。c,d位于全局作用域不是自动变量。

b. 捕获列表里只允许捕获上一层作用域的自动变量
c. 理解捕获的意义,理解值捕获,引用捕获差异,理解对上一层之上作用域内变量的使用

#include <iostream>

int a = 1;
static int b = 1;

int fun(int c){
    int d = 1;
    int dd = 11;
    auto f = [d, &c]()->int{
        int n1 = c + d;
        int n2 = a + b /*+ dd*/;
        printf("a_%d,b_%d,c_%d,d_%d,n1_%d,n2_%d\n", a,b,c,d,n1, n2);
    };

    f();
    c = 2;
    d = 2;
    a = 11;
    f();
    return 0;
}

int main(){
    fun(11);
    return 0;
}

在这里插入图片描述
c.1.捕获的意义是针对上一层作用域内的自动变量只有先被捕获,然后才可在lambda作用域内去使用。上一层之上作用内的变量无需捕获就能使用。
c.2.值捕获和引用捕获差异在将lambda转化为等价的可调用类型后则很好理解

#include <iostream>

int a = 1;
static int b = 1;

int fun(int c){
    int d = 1;
    int dd = 11;
    auto f = [d, &c]()->int{
        int n1 = c + d;
        int n2 = a + b /*+ dd*/;
        printf("a_%d,b_%d,c_%d,d_%d,n1_%d,n2_%d\n", a,b,c,d,n1, n2);
        c = 0;
    };

    class None{
    public:
        None(int d, int& c):m_d(d), m_c(c){
        }

        int operator()() const{
            int n1 = m_c + m_d;
            int n2 = a + b /*+ dd*/;
            printf("a_%d,b_%d,c_%d,d_%d,n1_%d,n2_%d\n", a,b,m_c,m_d,n1, n2);
            m_c = 0;
        }
    private:
        int m_d;
        int& m_c;
    };
    None none(d, c);

    f();
    printf("c_now_%d\n", c);
    none();
    printf("c_now_%d\n", c);
    c = 2;
    d = 2;
    a = 11;
    f();
    printf("c_now_%d\n", c);
    none();
    printf("c_now_%d\n", c);
    return 0;
}

int main(){
    fun(11);
    return 0;
}

在这里插入图片描述
上述定义了和lambda等价的可调用类型。易于观察到值捕获,引用捕获的差异。
c.3.理解lambda中对上一层之上作用域内变量的使用
参考c.2中等价的可调用类型,lambda产生了一个匿名内部可调用类型。内部类型可直接使用上一层之上作用域内的变量,且这类变量不像捕获的上一层作用域的自动变量,不会成为可调用类型的成员变量。
c.4.理解lambda定义,通过lambda对象执行调用两处时间点。
参考c.2中等价的可调用类型,lambda定义处不仅定义了一个匿名内部可调用类型,还实例化了一个该类型的对象实例。通过捕获列表完成了实例的构造。通过lambda对象执行调用只是在通过实例对象执行其operator()操作符调用。

2.2.parameters
这部分等价于可调用类型中重载的operator()操作符的形参列表。
值得注意的是当形参列表为空时,(parameters)部分可省略。

2.3.mutable
借助c.2中等价的可调用类型很好理解。lambda对应的可调用类型里operator()操作符是const修饰的,这意味者无法在lambda的作用域中修改捕获的变量。添加mutable修饰后,则可以。

值得注意的是:
a. 只有需要在lambda作用域内修改捕获的自动变量时,才需要添加mutable修饰。
b. 对于引用捕获的自动变量。引用本身是常量,但引用指向的底层对象并非常量。所以,作用域中通过引用捕获的变量执行赋值是允许的。参考2.1部分的c.2lambda作用域内执行c=0;

2.4.-> return-type
这部分等价于可调用类型中重载的operator()操作符的返回类型。

值得注意的是:
a. 这里采用了后置返回类型
b. -> return-type部分可省略,省略时,从lambda作用域内return语句自动推断返回类型。

2.5.{ statement }
这部分等价于可调用类型中重载的operator()操作符的{ statement }

文章来源:https://blog.csdn.net/x13262608581/article/details/135421501
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。