如何在 lambda 表达式中传递变量?

Posted

技术标签:

【中文标题】如何在 lambda 表达式中传递变量?【英文标题】:How to pass variables in a lambda expression? 【发布时间】:2019-12-03 14:51:51 【问题描述】:

我现在正在练习 lambda 表达式,我做的这个程序是获取一个主题的加权平均值,第一个 lambda 表达式 'get_avg' 是获取数据,而过程是 'sum_avg',当 sum_avg 运行时输出 '-nan(ind)',这不是我想要的答案。

#include<iostream>
#include<thread>
using namespace std;
int main() 
float m = 0, w = 0;
auto get_avg = [](float m, float w) 

    cout << "ENTER THE GRADE: ";
    cin >> m;
    cout << "ENTER THE UNITS: ";
    cin >> w;
    return m, w;
;
get_avg(m, w);
auto sum_avg = [](float m,float w)
    cout << "THE WEIGHTED AVERAGE IS :" <<m*w/w << endl;
;
sum_avg(m,w);
system("PAUSE");
return 0;

【问题讨论】:

另外,在 C++ 中,您不能从函数返回多个值。 return m, w; 行的行为与 return w 一样,因为 m, w 表达式使用逗号运算符,它只返回其右操作数。 (作为参考,在较新的标准中你可以使用结构化绑定的东西,但我现在不推荐它) 这个例子有点哲学上的难题。您有一个未命名的函数 (lambda),您将其命名为 get_avg。那为什么不使用普通的(命名的)函数呢? @MSalters get_avg 只存在于main 的范围内(在这种情况下不是很好的理由) 【参考方案1】:

为了能够更改main-function 的mw 的值,您需要通过引用将它们传递给get_avg lambda:

// you didn't need <thread> header, don't include it
#include<iostream>

// Never ever take the whole std namespace into your program!
// Take only the names you need,
// or just use the fully qualified names, e.g. std::cout everywhere.
using std::cin;
using std::cout;
using std::endl;

int main() 
    float m = 0, w = 0;
    auto get_avg = [](float &m, float &w) 
        cout << "ENTER THE GRADE: ";
        cin >> m;
        cout << "ENTER THE UNITS: ";
        cin >> w;
    ;
    get_avg(m, w);
    auto sum_avg = [](float m,float w)
        cout << "THE WEIGHTED AVERAGE IS :" <<m*w/w << endl;
    ;
    sum_avg(m,w);
    system("PAUSE");  // I'm not sure why you use this here.
    return 0;

您也可以按值获取变量,并从第一个 lambda 中返回 std::pair。然后你可以使用std::tie 将其返回值分配给mw

#include <iostream>
#include <tuple>
#include <utility>

int main() 
    float m = 0, w = 0;
    auto get_avg = [](float m, float w) 
        std::cout << "ENTER THE GRADE: ";
        std::cin >> m;
        std::cout << "ENTER THE UNITS: ";
        std::cin >> w;
        return std::make_pair(m, w);
    ;
    std::tie(m, w) = get_avg(m, w);
    auto sum_avg = [](float m, float w)
        std::cout << "THE WEIGHTED AVERAGE IS :" << m*w/w << std::endl;
    ;
    sum_avg(m, w);
    return 0;

顺便说一句,这个m*w/w 并没有做太多,我让你弄清楚原因。

【讨论】:

所以为了传递它,我必须使用他们的指针来调整来自该变量的数据? 这是一个reference, not a pointer。但是是的,如果你想改变变量的值,你需要通过引用而不是值来传递它们。【参考方案2】:

您的第一个 lambda 没有返回您所期望的。 您必须首先了解comma operator 才能意识到return m, w; 并不像您想象的那样工作。 实际上它返回w

其次,你打电话给get_avg(m, w),但不关心结果。 mw 是 lambda 的参数(局部变量),隐藏了外部作用域的 mw 变量。

您可以使用 lambda capture 来解决您的问题,或者让您的第一个 lambda 返回一个 std::pair&lt;float, float&gt; 并将它们注入您的第二个 lambda:

int main() 
float m = 0, w = 0;
// [&]  means Capture any referenced variable by reference
auto get_avg = [&]() 
    cout << "ENTER THE GRADE: ";
    cin >> m;
    cout << "ENTER THE UNITS: ";
    cin >> w;
;
get_avg(m, w);
auto sum_avg = [&]()
    cout << "THE WEIGHTED AVERAGE IS :" <<m*w/w << endl;
;
sum_avg(m,w);
system("PAUSE");  // I'm not sure why you use this here.
return 0;

澄清一下:

[] 什么都抓不到(或者,焦土战略?) [&amp;] 通过引用捕获任何引用的变量 [=] 通过复制来捕获任何引用的变量 [=, &amp;foo] 通过复制捕获任何引用的变量,但通过引用捕获变量foo [bar] 通过复制捕获bar;不要复制任何其他内容 [this] 捕获封闭类的this 指针

捕获可能很棘手,因为它取决于 lambda 定义的范围。如果您返回一个 lambda,您将捕获(无效)对不再存在的局部变量的引用。

【讨论】:

请问我可以在 '[]' 中使用哪些其他运算符? @JansenLloydMacabangun 这是一个太宽泛的问题,无法发表评论。 en.cppreference.com/w/cpp/language/lambda 详细介绍了 lambda。

以上是关于如何在 lambda 表达式中传递变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用lambda表达式捕获局部变量?

如何在 lambda 表达式中使用局部变量

如何更改 lambda 表达式中的字符串变量?

Lambda 表达式以及如何组合它们?

Lambda 表达式和变量捕获

C++ lambda 表达式传递的变量默认不可变