我知道对于 non-noob sendmail_path = /usr/local/bin/catchmail -f someone@domain.com
开发人员来说这似乎很愚蠢,但是这4个lambda表达式之间有什么区别?
Code:
C++
似乎也一样吗?是使用两种不同的“符号”,还是将值用作闭包?
答案 0 :(得分:7)
在这种情况下,它们都产生相同的结果。但是,它们之间存在逻辑差异。
[](double value) { return MyFunction(value, 1.0, 2.0); }
这是一个lambda,它接受类型为value
的单个参数,并将其传递给MyFunction
。从return
语句推断出它的返回类型为MyFunction
的返回类型,即double.
[](double value) -> double { return MyFunction(value, 1.0, 2.0); }
这与以前的lambda相同,但是这次将其返回类型显式指定为double
。在这种情况下是相同的,但是如果MyFunction
的返回类型是其他类型,则它将与第一个不同。在这种情况下,第一个将返回MyFunction
返回的内容,而第一个仍将返回double
。
[value](double value) { return MyFunction(value, 1.0, 2.0); }
这取决于所使用的标准版本。在C ++ 11和14中,该变量捕获main
的局部变量value
。但是,该捕获被lambda的参数value
隐藏,因此实际上是无用的。如果lambda被声明为例如[value](double v) { return MyFunction(value, 1.0, 2.0); }
。这将传递给捕获的value
,而不是其参数。
在C ++ 17及更高版本中,它已更改,并且实际上是格式错误的(编译错误)。不再允许将lambda参数命名为与您捕获的参数相同的名称。
由于更改是缺陷报告(CWG 2211),因此它是追溯应用的,因此即使在早期的C ++版本中,编译器也拒绝此类代码是合法的。
[value](double value) -> double { return MyFunction(value, 1.0, 2.0); }
与lambda数字3相同,具有明确的返回类型说明(3和4之间的差与1和2之间的差完全相同)。
答案 1 :(得分:5)
第二个lambda与第一个lambda不同,因为您已明确指定返回类型。由于推导的第一个lambda的返回类型相同,因此没有区别。
第三和第四个lambda格式错误,因为它们声明的参数名称与捕获名称相同。参见标准规则:
[expr.prim.lambda.capture]
如果简单捕获中的标识符显示为lambda声明符的parameter-claration-clause子句的参数的声明符-id,则程序格式错误。 [示例:
void f() { int x = 0; auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name }
-示例 ]
此措辞在C ++ 17中被采用。
答案 2 :(得分:3)
第一个lambda是常规的。
第二个lambda表示其返回类型为double
。
最后两个lambda没声音。 value
都是通过值及其参数捕获的,不应尝试使用它(警告表示捕获无法正常进行)。要么是参数,要么是捕获的变量(按值或ref)。
我想,它们应该是这样的:
[foo](double value) { return MyFunction(value, 1.0, foo); }, value);
答案 3 :(得分:1)
第一个和第二个lambda之间以及第三个和第四个lambda之间的区别是,您明确指定或不指定返回类型。在这里它产生相同的功能。
前两个Lambda和第三个Lambda和第四个Lambda之间的差异正在捕获。但是您的示例不适合说明捕获的效果。查看以下代码(live demo)。
int main()
{
double v = 100.0;
auto lam1= [](double val) { return MyFunction(val, 1.0, 2.0); }; //A
auto lam2= [v](double val) { return MyFunction(v, 1.0, 2.0); }; //B
auto lam3= [&v](double val) { return MyFunction(v, 1.0, 2.0); }; //C
FunctionWrapper( lam1, v++ ); //1
FunctionWrapper( lam2, v++ ); //2
FunctionWrapper( lam3, v++ ); //3
std::cout << "v: " << v << '\n';
}
虽然lam1
没有捕获任何内容,但是lam2
通过值捕获了v
,而lam3
通过引用捕获了v
。三个FunctionWrapper
调用的输出分别是103、103、106。这是因为尽管v
在//1
行中已更改,但它的旧值仍在//2
行中使用。也就是说,按值捕获意味着v
在行lam2
中初始化//B
时保存的值lam2
存储在//3
中。另一方面,在v
行中,使用lam3
的当前值。这是因为v
拥有对{{1}}的引用。