简体   繁体   English

C++ lambda:Currying sum 函数:使用按值捕获与按引用捕获返回不同的结果

[英]c++ lambda: Currying sum function: returns different results using capture by value vs by reference

I have a very simple recursive lambda which calculates sum of given 2 numbers:我有一个非常简单的递归 lambda,它计算给定 2 个数字的总和:

auto sum_v1 = [](auto first){
  return [first](auto second){
    return first + second;
  };
};

sum_v1 (1)(2); // returns 3, OK

Now the same function, using capture by reference for arg first.现在使用相同的函数,首先对 arg 使用按引用捕获。

auto sum_v2 = [](auto first){
  return [&first](auto second){
    return first + second;
  };
};

sum_v2 (1)(2); // returns 4, NOT OK

sum_v2 gets the argument first as 2 and arg second is also 2 . sum_v2获取参数first2和Arg second也是2

I know how to get the right result.我知道如何获得正确的结果。 I could use either the sum_v1 OR sum_v3 (shown below).我可以使用 sum_v1 或 sum_v3(如下所示)。

// accept arg first using r-value reference
auto sum_v3 = [](auto&& first){
  return [first](auto second){
    return first + second;
  };
};

sum_v3 (1)(2); // returns 3, OK

How is sum_v2 , while creating the lambda, is seeing the arg first as 2. I am struggling to understand that. sum_v2在创建 lambda 时如何first将 arg 视为 2。我正在努力理解这一点。

Could you please give me some hint(s) to understand this better?你能给我一些提示以更好地理解这一点吗? I am using gcc.9.2.0 with -std=c++17 on rhel 7.我在 rhel 7 上使用带有 -std=c++17 的 gcc.9.2.0。

Thanks, Gaurav谢谢,高拉夫

This:这个:

auto sum_v2 = [](auto first){
  return [&first](auto second){
    return first + second;
  };
};

Is undefined behavior, as you are taking a reference to a local variable first whose lifetime ends before it is used.是未定义的行为,因为您first引用局部变量,该变量的生命周期在使用之前结束。 As with all UB, anything could happen.与所有 UB 一样,任何事情都可能发生。 On your machine it seems that first ends up referencing second instead, but that's not guaranteed.在您的机器上,似乎first最终会引用second ,但这并不能保证。 The code could crash on other systems, or produce the expected result, but you can't rely on it.代码可能会在其他系统上崩溃,或产生预期的结果,但您不能依赖它。

With -Wall -Werror you wouldn't even be able to compile this bad code.使用-Wall -Werror你甚至无法编译这个糟糕的代码。 Demo: https://godbolt.org/z/3gYx7q演示: https : //godbolt.org/z/3gYx7q

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM