C++的lambda

在现代C++编程中,Lambda表达式因其简洁性与灵活性而成为一种强大且广泛使用的工具。它们为开发者提供了一种优雅的方式来定义匿名函数,使代码更具可读性和可维护性。无论是在处理回调函数、与标准模板库(STL)的算法结合,还是简化并行计算中,Lambda表达式都展示了它的不可替代性。在这篇博客中,我们将深入探讨Lambda的语法、用法,以及它在实际开发中的应用场景,帮助你全面掌握这一现代C++的关键特性。

在这里插入图片描述
可以值传递,也可以引用 传递
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

为什么报错

在这里插入图片描述

ChatGpt解答:

是的,代码在 ForEach(values, lambda) 这一行会报错。问题出在 ForEach 函数的参数类型和 lambda 表达式的类型不匹配。

ForEach 函数接受一个指向函数的指针作为第二个参数,即 void(*func)(int)。但是你传递的是一个 lambda 表达式,lambda 是一种闭包(closure),它可以捕获外部变量,默认情况下它不能隐式转换为函数指针。

要解决这个问题,可以选择以下几种方法之一:

方法一:使用 std::function

你可以使用 std::function 来接受 lambda 表达式:

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

void ForEach(const std::vector<int>& values, std::function<void(int)> func)
{
    for (int value : values)
        func(value);
}

int main()
{
    std::vector<int> values = { 1, 5, 4, 2, 3 };
    int a = 5;
    auto lambda = [=](int value) { std::cout << "Value: " << value << std::endl; };
    ForEach(values, lambda);
    std::cin.get();
}

方法一的增强版

使用 const std::function<void(int)>& func 作为参数是可行的,并且在某些场景下更合适。让我们看看它与我之前提供的代码中使用的 std::function<void(int)> func 有什么区别。

1. 传递方式的区别
  • std::function<void(int)> func:按值传递。std::function 对象会被复制,这可能会带来一些性能开销,尤其是当捕获的状态很复杂或当函数对象本身比较大时。

  • const std::function<void(int)>& func:按引用传递。这里传递的是对 std::function 对象的引用,不会产生复制开销。由于是 const 引用,传入的 std::function 无法在函数内部被修改。

2. 性能影响
  • 使用引用传递通常会比按值传递更高效,特别是当 std::function 对象包含大量捕获的状态或内部结构比较复杂时。引用传递避免了不必要的复制操作。
3. 使用场景
  • 如果你只需要在函数中使用 std::function 而不需要修改它,使用 const std::function<void(int)>& 会更合适。
  • 如果你需要修改 std::function 对象,或者你希望函数内部持有 std::function 的副本,那么按值传递 std::function<void(int)> 是合适的。
修改后的代码示例

使用 const std::function<void(int)>&

#include <iostream>
#include <vector>
#include <functional>

void ForEach(const std::vector<int>& values, const std::function<void(int)>& func)
{
    for (int value : values)
        func(value);
}

int main()
{
    std::vector<int> values = {1, 5, 4, 2, 3};
    auto lambda = [](int value) { std::cout << "Value: " << value << std::endl; };
    ForEach(values, lambda);
    std::cin.get();
}
总结

const std::function<void(int)>& 更适合避免不必要的复制操作,因此在很多情况下,这是一种更优的选择。如果你不需要在函数内部修改 std::function 对象,这是一个推荐的方式。

方法二:不捕获外部变量

如果 lambda 表达式不捕获任何外部变量(例如 [=][&]),它可以自动转换为一个函数指针:

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

void ForEach(const std::vector<int>& values, void(*func)(int))
{
    for (int value : values)
        func(value);
}

int main()
{
    std::vector<int> values = { 1, 5, 4, 2, 3 };
    auto lambda = [](int value) { std::cout << "Value: " << value << std::endl; };
    ForEach(values, lambda);
    std::cin.get();
}

方法三:直接传递函数指针

你可以定义一个普通的函数,并传递它的指针给 ForEach

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

void PrintValue(int value)
{
    std::cout << "Value: " << value << std::endl;
}

void ForEach(const std::vector<int>& values, void(*func)(int))
{
    for (int value : values)
        func(value);
}

int main()
{
    std::vector<int> values = { 1, 5, 4, 2, 3 };
    ForEach(values, PrintValue);
    std::cin.get();
}

你可以选择适合你需求的方法来修复这个问题。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值