当前位置:   article > 正文

C++匿名函数lamba简介

C++匿名函数lamba简介

一、定义

Lambda 表达式是 C++11 引入的一个功能,允许你在代码中定义匿名函数(即没有名字的函数)。这种表达式可以用于简化函数对象的定义,并使得代码更简洁。Lambda 表达式特别适用于局部的、一次性的函数对象,如用于 STL 算法中。

二、基本语法

[捕获列表](参数列表)mutable(可选)异常属性 -> 返回类型(可省略){
// 函数体
}
返回类型可自动推导,但是如果有多个return语句还是要显示指定。


int main() {
	auto Add = [](int a, int b)->int {
		return a + b;
	}
	std::cout << Add(1, 2) << std::endl;	// 输出3
	return 0;
}

int main() {
	auto Add = [](int a, int b) {
		return a + b;
	}
	std::cout << Add(1, 2) << std::endl;	// 输出3
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

三、捕获列表

  1. 值捕获

用 ‘=’ 表示,前提是捕获的变量可以拷贝,在表达式被创建的时候即捕获,捕获的变量即使后面被更改也不会改变函数体内的值。


void main()
{
    int c = 12;
    int d = 30;
    auto Add = [c, d](int a, int b)->int {
        cout << "d = " << d  << endl;	// 打印30
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;	// 输出3
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. 引用捕获

用 ‘&’ 表示,引用捕获保存的是变量的引用,值可以修改。


void main()
{
    int c = 12;
    int d = 30;
    auto Add = [&c, &d](int a, int b)->int {
        c = a;
        cout << "d = " << d  << endl;	// c的值被改为1,打印20
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;	// 输出3
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 隐式捕获

就是用按值捕获和按引用捕获的标识来表示,不指定具体变量,捕获范围是外部所有变量。


void main()
{
    int c = 12;
    int d = 30;
    auto Add = [&](int a, int b)->int {	// &可以换成=,也可以&,=同时使用称为混合捕获
        c = a;
        cout << "d = " << d  << endl;	// 打印20
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;	// 打印3
    std::cout << "c:" << c<< std::endl;		// 打印1
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 空捕获

即捕获列表为空,函数体内不可以使用任何外部变量。


void main()
{
    int c = 12;
    int d = 30;
    auto Add = [](int a, int b)->int {
        c = a;	// 报错
        cout << "d = " << d  << endl;	// 报错
        return c;
    };
    d = 20;
    std::cout << Add(1, 2) << std::endl;
    std::cout << "c:" << c<< std::endl;	
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  1. 表达式捕获

即允许捕获的变量用表达式表示,即可捕获右值,捕获变量的类型由编译器根据表达式自动推导。


void main()
{
    auto important = std::make_unique<int>(1);
    auto add = [v1 = 1, v2 = std::move(important)](int x, int y) -> int {
        return x + y + v1 + (*v2);
    };

    std::cout << add(3,4) << std::endl;		// 打印9
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 泛型Lambda

即表达式传入的形参可以用auto关键字表示,自动推导传入的参数的类型。


void main()
{
    auto add = [](auto x, auto y) {
        return x+y;
    };

    std::cout <<  add(1, 2) << std::endl;		// 打印3
    std::cout <<  add(1.1, 1.2) << std::endl;	// 打印3.3
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 可变Lambda

采用值捕获的方式不可以改变外部变量,但是可以通过加mutable关键字修饰的方式也可以修改值捕获的外部变量。


void main() {
    int v = 5;
    auto ff = [v]() mutable {return ++v;};
    v = 0;
    auto j = ff();  // j为6
    cout << "j:" << j << endl;	// 打印0
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

四、总结

捕获方式含义
[ ]空捕获列表,Lambda不能使用所在函数中的变量.
[names]names是一个逗号分隔的名字列表,这些名字都是Lambda所在函数的局部变量。默认情况下,这些变量会被拷贝,然后按值传递,名字前面如果使用了&,则按引用传递
[&]隐式捕获列表,Lambda体内使用的局部变量都按引用方式传递
[=]隐式捕获列表,Lanbda体内使用的局部变量都按值传递
[&,identifier_list]identifier_list是一个逗号分隔的列表,包含0个或多个来自所在函数的变量,这些变量采用值捕获的方式,其他变量则被隐式捕获,采用引用方式传递,identifier_list中的名字前面不能使用&。
[=,identifier_list]identifier_list中的变量采用引用方式捕获,而被隐式捕获的变量都采用按值传递的方式捕获。identifier_list中的名字不能包含this,且这些名字面前必须使用&。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/1002678
推荐阅读
相关标签
  

闽ICP备14008679号