c ++ lambda:Currying sum 函数:returns 使用按值捕获与按引用捕获的不同结果
c++ lambda: Currying sum function: returns different results using capture by value vs by reference
我有一个非常简单的递归 lambda,它计算给定 2 个数字的总和:
auto sum_v1 = [](auto first){
return [first](auto second){
return first + second;
};
};
sum_v1 (1)(2); // returns 3, OK
现在相同的函数,首先对 arg 使用引用捕获。
auto sum_v2 = [](auto first){
return [&first](auto second){
return first + second;
};
};
sum_v2 (1)(2); // returns 4, NOT OK
sum_v2
获取参数 first
作为 2
并且参数 second
也是 2
.
我知道如何得到正确的结果。我可以使用 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
sum_v2
如何在创建 lambda 时将 arg first
视为 2。我很难理解这一点。
能否请您给我一些提示以更好地理解这一点?我在 rhel 7 上使用 gcc.9.2.0 和 -std=c++17。
谢谢,
高拉夫
这个:
auto sum_v2 = [](auto first){
return [&first](auto second){
return first + second;
};
};
是未定义的行为,因为您正在引用局部变量 first
,其生命周期在使用前结束。与所有 UB 一样,任何事情都可能发生。在您的机器上,first
似乎最终引用了 second
,但这并不能保证。该代码可能会在其他系统上崩溃,或产生预期的结果,但您不能依赖它。
使用 -Wall -Werror
,您甚至无法编译此错误代码。演示:https://godbolt.org/z/3gYx7q
我有一个非常简单的递归 lambda,它计算给定 2 个数字的总和:
auto sum_v1 = [](auto first){
return [first](auto second){
return first + second;
};
};
sum_v1 (1)(2); // returns 3, OK
现在相同的函数,首先对 arg 使用引用捕获。
auto sum_v2 = [](auto first){
return [&first](auto second){
return first + second;
};
};
sum_v2 (1)(2); // returns 4, NOT OK
sum_v2
获取参数 first
作为 2
并且参数 second
也是 2
.
我知道如何得到正确的结果。我可以使用 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
sum_v2
如何在创建 lambda 时将 arg first
视为 2。我很难理解这一点。
能否请您给我一些提示以更好地理解这一点?我在 rhel 7 上使用 gcc.9.2.0 和 -std=c++17。
谢谢, 高拉夫
这个:
auto sum_v2 = [](auto first){
return [&first](auto second){
return first + second;
};
};
是未定义的行为,因为您正在引用局部变量 first
,其生命周期在使用前结束。与所有 UB 一样,任何事情都可能发生。在您的机器上,first
似乎最终引用了 second
,但这并不能保证。该代码可能会在其他系统上崩溃,或产生预期的结果,但您不能依赖它。
使用 -Wall -Werror
,您甚至无法编译此错误代码。演示:https://godbolt.org/z/3gYx7q