C++ lambda表达式

2年前 (2022) 程序员胖胖胖虎阿
175 0 0

lambda表达式也称匿名函数,c++11新增内容。

语法如下:

/*
参数说明:
capture list:    捕获列表,是一个lambda所在函数中定义的局部变量列表
parameter list: 参数列表
return type:    返回类型
function body:  函数体
*/
[capture list] (parameter list) -> return type {function body}

lambda表达式可以理解为可调用的代码单元,

可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体

    auto ret = []() {
        return 5;
    };
    cout << ret() << endl;

C++ lambda表达式


值捕获

值捕获的前提是变量可以拷贝。变量的值是在lambda创建时拷贝,而不是调用时拷贝,因此其修改不会影响到lambda内部对应的值。

默认情况下:如果以传值方式捕获外部变量,则在Lambda表达式函数体中不能修改该外部变量的值。

当按值的方式获取外部变量时,是无法更改获取过来的值的,除非使用mutable关键字声明,就可以更改(更改的不是外部变量原本地址里的值,而是lambda函数体内的副本);

int main()
{
    int num = 2;
    auto ret = [num] () { return num; };
    num += 2;
    cout << ret() << endl; //输出 2
    cout << num << endl; //输出 4
    return 0;
}

引用捕获

当按引用的方式捕获外部变量时,lambda函数体内可以更改此值,更改的是外部变量原本地址里的值;

int main()
{
    int num = 2;
    auto ret = [&num] () { return num; };
    num += 2;
    cout << ret() << endl; //输出 4
    cout << num << endl; //输出 4
    return 0;
}

隐式捕获

隐式捕获有两种方式,分别是[=]和[&]。[=]表示以值捕获的方式捕获外部变量,[&]表示以引用捕获的方式捕获外部变量

当按值的方式获取外部变量时,是无法更改获取过来的值的,除非使用mutable关键字声明,就可以更改(更改的不是外部变量原本地址里的值,而是lambda函数体内的副本);
当按引用的方式捕获外部变量时,lambda函数体内可以更改此值,更改的是外部变量原本地址里的值;

int main()
{
    int num = 2;

    //可以捕获外部变量
    auto ret = [=] () { 
        return num; 
    };
    //会报错 ,无法修改外部变量
    auto ret = [=]() {
        return num++;
    };
    

    //可以捕获外部变量
    auto ret = [&]() {
        return num;
    };
    //可以法修改外部变量
    auto ret = [&]() {
        return num++;
    };
    return 0;
}

混合方式捕获

lambda还支持混合方式捕获,即同时使用显示捕获和隐式捕获。

混合捕获时,捕获列表中的第一个元素必须是 = 或 &,此符号指定了默认捕获的方式是值捕获或引用捕获 。

需要注意的是:显示捕获的变量必须使用和默认捕获不同的方式捕获。

int main()
{
    int a = 2;
    int b = 3;

    auto f1 = [=, &a]() { return a + b; };        //正确,默认值捕获,显示是引用捕获
    auto f2 = [=, a]() { return a + b; };        //编译出错,默认值捕获,显示值捕获,冲突了
    auto f3 = [&, a]() { return a + b; };        //正确,默认引用捕获,显示是引用捕获
    auto f4 = [&, &a]() { return a + b; };        //编译出错,默认引用捕获,显示引用捕获,冲突了

    return 0;
}

修改值捕获的值

在Lambda表达式中,如果以传值方式捕获外部变量,则函数体中不能修改该外部变量,否则会引发编译错误。

如果你希望被值捕获的值被改变,就必须在参数列表首加上关键字mutable。

//语法
[capture list] (parameter list) mutable -> return type {function body}
int main()
{
    int num = 2;

    auto f1 = [num]()mutable { // 不会报错
        num++;
        cout << num << endl;
    };

    auto f2 = [=]()mutable { // 不会报错
        num++;
        cout << num << endl;
    };

    cout << num++ << endl;
    f1();
    f2();

    return 0;
}
  • 当按值的方式获取外部变量时,是无法更改获取过来的值的,除非使用mutable关键字声明,就可以更改(更改的不是外部变量原本地址里的值,而是lambda函数体内的副本);
  • 当按引用的方式捕获外部变量时,lambda函数体内可以更改此值,更改的是外部变量原本地址里的值;
  • 当在类中,lambda表达式捕获this指针时,lambda函数体内可以直接改变该类中的变量,和类中的普通函数拥有一样的权限。
版权声明:程序员胖胖胖虎阿 发表于 2022年9月10日 下午11:16。
转载请注明:C++ lambda表达式 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...