C++ C11 Lambda

1.目的

Lambda 表达式是 C++11 引入的一种特性,旨在提供一种简洁的方式来定义和使用匿名函数。Lambda 表达式可以直接在代码中定义和使用,不需要像普通函数那样在其它地方声明和定义。

2.基本语法

Lambda 表达式的基本语法如下:

[capture](parameters) -> return_type { body }

capture:捕获列表,指定哪些变量可以在 Lambda 表达式中使用。

parameters:参数列表,与普通函数的参数列表类似。

return_type:返回类型,可以省略,编译器会自动推断。

body:函数体,与普通函数的函数体类似。

3.示例

3.1 无参

#include <iostream>

int main() {
    auto lambda = []() {
        std::cout << "Hello, Lambda!" << std::endl;
    };

    lambda(); // 调用 Lambda 表达式

    return 0;
}

3.2 带参数

#include <iostream>

int main() {
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    std::cout << "Sum: " << add(3, 5) << std::endl;

    return 0;
}

3.3 带捕获列表

捕获列表用于指定哪些变量可以在 Lambda 表达式中使用。捕获列表有几种方式:

[=]:按捕获所有外部变量。

[&]:按引用捕获所有外部变量。

[this]:捕获当前对象的 this 指针。

[a, &b]:按值捕获 a,按引用捕获 b。

#include <iostream>

int main() {
    int x = 10;
    int y = 20;

    auto lambda1 = [=]() {
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };

    auto lambda2 = [&]() {
        x = 30; // 可以修改 x
        std::cout << "x: " << x << ", y: " << y << std::endl;
    };

    lambda1();
    lambda2();

    return 0;
}

3.4 返回类型

3.4.1自动推断

#include <iostream>

int main() {
    auto add = [](int a, int b) {
        return a + b; // 返回类型自动推断为 int
    };

    std::cout << "Sum: " << add(3, 5) << std::endl;

    return 0;
}

3.4.2 显式指定

#include <iostream>

int main() {
    auto divide = [](int a, int b) -> double {
        return static_cast<double>(a) / b;
    };

    std::cout << "Division: " << divide(10, 3) << std::endl;

    return 0;
}

3.5 Lambda 表达式在标准库中的应用

如 std::sort、std::for_each 等算法。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};

    // 使用 Lambda 表达式对 vector 元素进行排序
    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        return a > b; // 降序排序
    });

    // 使用 Lambda 表达式输出 vector 元素
    std::for_each(vec.begin(), vec.end(), [](int n) {
        std::cout << n << " ";
    });

    return 0;
}

4.注意事项

4.1 捕获的生命周期

捕获的变量在 Lambda 表达式的生命周期内必须有效。如果捕获的是局部变量且 Lambda 表达式在其作用域外使用,可能会导致未定义行为。错误示例:

        auto lambda;
        {
		    int x = 10;
		    lambda = [x]() {
		        std::cout << x << std::endl; // 未定义行为
		    };
		}
		lambda(); // x 已经超出作用域

4.2 捕获的方式

        int x = 10;
		auto lambda = [x]() mutable {
		    x = 20; // 允许修改 x
		    std::cout << x << std::endl;
		};
		lambda();
		std::cout << x << std::endl; // 原始 x 未修改

4.3 Lambda 表达式的类型

Lambda 表达式没有类型名,但可以使用 auto 或 std::function 来存储 Lambda 表达式

        #include <iostream>
		#include <functional>
		int main() {
		    auto lambda = [](int a, int b) {
		        return a + b;
		    };
		    std::function<int(int, int)> func = lambda;
		    std::cout << "Sum: " << func(3, 5) << std::endl;
		    return 0;
		}

4.4 使用mutable修饰

采用值捕获的方式 lambda 不能修改其值,如果想要修改, 使用 mutable 修饰
采用引用捕获的方式, lambda 可以直接修改其值

5.C14 扩展

5.1 捕获右值

在 C++14 之前的 C++11 中,Lambda 表达式只能捕获左值,不能直接捕获右值。这意味着如果你想要捕获一个右值,你必须先将其存储在一个局部变量中,然后捕获这个局部变量。

C++11 示例

#include <iostream>
#include <string>

int main() {
    std::string str = "Hello";
    auto lambda = [str]() mutable { std::cout << str << std::endl; }; // 捕获左值
    lambda();
    return 0;
}

在 C++14 中,Lambda 表达式可以直接捕获右值,通过 std::move 来实现移动捕获。这大大简化了代码,并且提高了性能,因为避免了不必要的拷贝。

C++14 示例

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

5.2 泛型 Lambda

C++14 开始, Lambda 函数的形式参数可以使用 auto 关键字来产生意义上的泛型
void function()
{
auto add = [](auto x, auto y) {
return x+y;
};
std::cout << add(1, 2) << std::endl;
std::cout << add(1.1, 1.2) << std::endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值